WinSocket实现进程通信的一个简单实例
2017-06-14 本文已影响45人
Umiade
Windows下通过Socket可以使进程之间产生通信。
设计上简单地分为服务端和客户端。
服务端:
1. 建立Socket
2. 声明自身的端口号和地址并绑定到Socket
3. 使用Listen打开监听,然后不断用Accept去查看是否有连接,如果有,捕获Socket,并通过Recv获取消息的内容
4. 通信完成后调用CloseSocket关闭这个对应Accept到的Socket,如果不再需要等待任何客户端连接,那么用CloseSocket关闭掉自身的Socket
客户端:
1. 建立Socket
2. 通过端口号和地址确定目标服务器,使用Connect连接到服务器
3. send发送消息,等待处理
4. 通信完成后调用CloseSocket关闭Socket
服务端代码:
#pragma once
/*
ServerNet.h
服务端:建立Socket,声明自身的端口号和地址并绑定到Socket,使用Listen打开监听,
然后不断用Accept去查看是否有连接,如果有,捕获Socket,并通过Recv获取消息的内容,
通信完成后调用CloseSocket关闭这个对应Accept到的Socket,如果不再需要等待任何客户端连接,那么用CloseSocket关闭掉自身的Socket
*/
#include<stdio.h>
#include<windows.h>
#pragma comment(lib, "Ws2_32.lib")
class ServerNet
{
private:
SOCKET m_sock;
public:
// 初始化服务器
int ServerInit(const char* address, int port);
// 更新数据
void ServerRun();
};
/*
ServerNet.cpp
*/
#include"ServerNet.h"
/*服务器初始化*/
int ServerNet::ServerInit(const char* address, int port)
{
int rlt = 0;
int iErrorMsg;
//初始化WinSock
WSAData wsaData;
iErrorMsg = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (iErrorMsg != NO_ERROR)
{
//初始化WinSock失败
printf("server wsastartup failed with error : %d\n", iErrorMsg);
rlt = 1;
return rlt;
}
// 创建服务器端socket
m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_sock == INVALID_SOCKET)
// 创建socket出现了异常
{
printf("server socket failed with error: %d\n", WSAGetLastError());
rlt = 2;
return rlt;
}
// 声明信息
SOCKADDR_IN servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = port;
servaddr.sin_addr.s_addr = inet_addr(address);
//绑定
iErrorMsg = bind(m_sock, (SOCKADDR*)&servaddr, sizeof(servaddr));
if (iErrorMsg < 0)
{
//绑定失败
printf("bind failed with error : %d\n", iErrorMsg);
rlt = 3;
return rlt;
}
return rlt;
}
void ServerNet::ServerRun()
{
// 公开连接
listen(m_sock, 5);
SOCKADDR_IN tcpAddr;
int len = sizeof(sockaddr);
SOCKET newSocket;
char buf[1024];
int rval;
do
{
// 接收信息
newSocket = accept(m_sock, (sockaddr*)&tcpAddr, &len);
if (newSocket == INVALID_SOCKET)
{
// 非可用socket
printf("invalid socket occured.\n");
}
else
{
// 可用的新socket连接
printf("new socket connect: %d\n", newSocket);
// 消息处理
do
{
//printf("process\n");
// 接收数据
memset(buf, 0, sizeof(buf));
rval = recv(newSocket, buf, 1024, 0);
if (rval == SOCKET_ERROR)
// 该异常通常发生在未closeSocket就退出时
{
printf("recv socket error.\n");
break;
}
else if (rval == 0)
// 0表示正常退出
printf("socket %d connect end.\n", newSocket);
else
// 显示接收到的数据
printf("recv msg: %s\n", buf);
} while (rval != 0);
// 关于接收的socket
closesocket(newSocket);
}
} while (1);
// 关闭自身socket
closesocket(m_sock);
}
客户端代码:
/*
ClientNet.cpp
*/
#include"ClientNet.h"
/*客户端Socket连接*/
int ClientNet::ClientConnect(int port, const char* address)
{
int rlt = 0; //connectflag 0-success 1-WSAStartfailed 2-socketfailed 3-connectfailed
// 记录错误信息
int iErrMsg;
// 启动WinSock
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 1);
iErrMsg = WSAStartup(wVersionRequested, &wsaData);
if (iErrMsg != NO_ERROR)
// WSAStartup出现了错误
{
printf("failed with WSAStartup error: %d\n", iErrMsg);
rlt = 1;
return rlt;
}
// 创建Socket
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_sock==INVALID_SOCKET)
// socket出现了错误
{
printf("failed with socket error: %d\n", WSAGetLastError());
rlt = 2;
return rlt;
}
// 目标服务器数据
SOCKADDR_IN servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = port;
servaddr.sin_addr.s_addr = inet_addr(address);
// sock与目标服务器连接
iErrMsg = connect(m_sock, (SOCKADDR*)&servaddr, sizeof(servaddr));
if (iErrMsg != NO_ERROR)
{
printf("failed with connect error: %d\n", iErrMsg);
rlt = 3;
return rlt;
}
// success
return rlt;
}
/*客户端发送消息*/
int ClientNet::ClientSend(const char* msg, int len)
{
int rlt = 0;
int iErrMsg = 0;
// 指定sock发送消息
iErrMsg = send(m_sock, msg, len, 0);
if (iErrMsg < 0)
// 发送失败
{
printf("send msg failed with error: %d\n", iErrMsg);
rlt = 1;
return rlt;
}
printf("send msg successfully\n");
return rlt;
}
/*客户端关闭Socket*/
void ClientNet::ClientClose()
{
closesocket(m_sock);
}
简单交互:
#include<iostream>
#include<string>
#include"ClientNet.h"
using namespace std;
int main()
{
ClientNet client;
int rlt = 0;
string msg;
//memset(msg, 0, sizeof(msg));
//连接到127.0.0.1(即本地),端口号为8888的服务端
printf("connecting.....\n");
rlt = client.ClientConnect(8888, "127.0.0.1");
if (rlt == 0)
// socket连接成功
{
//发送消息
printf(" connect successfully. input q to quit\n");
printf("-------------------------\n");
while (1)
{
printf("msg input: ");
getline(cin, msg);
if (msg == "q")
break;
else
{
printf("sending msg.....\n");
rlt = client.ClientSend(msg.c_str(), msg.length());
}
}
// 关闭socket
printf("closing socket.....\n");
client.ClientClose();
}
system("pause");
return 0;
}
通信试例结果