参考了:http://www.cnblogs.com/jzincnblogs/p/5189636.html 给了很大的启示
话不多说,直接上码。
服务器端
服务器端头文件(server.h)
#ifndef SERVER_H
#define SERVER_H
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
class Server
{
public:
Server();
~Server();
void WaitForClient();
private:
WORD winsock_ver;
WSADATA wsa_data;
SOCKET sock_svr;
SOCKET sock_clt;
HANDLE h_thread;
SOCKADDR_IN addr_svr;
SOCKADDR_IN addr_clt;
int res_val;
int addr_len;
char buf_IP[129];
};
struct Parameter//用来传参 使得CreateThread()可以传递多个参数
{
SOCKET sock_clt;
SOCKADDR_IN addr_clt;
};
#endif
服务器端(server.cpp)
#include "server.h"
#include<iostream>
#include<WS2tcpip.h>
#include<string.h>
using namespace std;
#define SER_PORT 8888
#define MaxSize 500
Server::Server()//构造函数
{
//初始化winsock
winsock_ver = MAKEWORD(2,2);
addr_len = sizeof(SOCKADDR_IN);
addr_svr.sin_family = AF_INET;
addr_svr.sin_port = htons(SER_PORT);
addr_svr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
memset(buf_IP,0,sizeof(buf_IP));
res_val = WSAStartup(winsock_ver,&wsa_data);
if(res_val != 0)
{
cout<<"WSAStratup error!"<<endl;
exit(1);
}
cout<<"WSAStartup successfully..."<<endl;
//创建socket
sock_svr = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sock_svr == INVALID_SOCKET)
{
cout<<"Failde to create server socet!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
//绑定socket
res_val = bind(sock_svr,(LPSOCKADDR)&addr_svr,addr_len);
if(res_val == SOCKET_ERROR)
{
cout<<"Failed to bind server socket!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
//监听socket
res_val = listen(sock_svr,5);
if(res_val == SOCKET_ERROR)
{
cout<<"Failed to listen server socket!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
cout<<"Server socket start to listen..."<<endl;
cout<<"Server started successfully..."<<endl;
}
Server::~Server()//析构函数
{
//关闭socket
closesocket(sock_svr);
closesocket(sock_clt);
WSACleanup();
cout<<"socket close..."<<endl;
}
//先声明CreateClientThread(LPVOID lpParamter),因为WaitForClient()函数会用到
void CreateClientThread(LPVOID lpParamter);
void Server::WaitForClient()//需要accept()以及创建thread
{
while(true)
{
sock_clt = accept(sock_svr,(LPSOCKADDR)&addr_clt,&addr_len);
Parameter para_clt;//用来传参数
para_clt.sock_clt = sock_clt;
para_clt.addr_clt = addr_clt;
if(sock_clt == SOCKET_ERROR)
{
cout<<"Failde to accept client!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
strcpy(buf_IP,inet_ntoa(addr_clt.sin_addr));//获取客户端IP
cout<<"A new client connect! IP:"<<buf_IP<<" PORT:"<<ntohs(addr_clt.sin_port)<<endl;
//创建线程
h_thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CreateClientThread,(LPVOID)¶_clt,0,0);
if(h_thread == NULL)
{
cout<<"Fail to create a new thread!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
CloseHandle(h_thread);
}
}
void CreateClientThread(LPVOID lpParamter)//实现对客户端的消息接收
{
Parameter* para_clt = (Parameter*)lpParamter;//需要注意此处的指针类型
SOCKET sock_clt = para_clt->sock_clt;
SOCKADDR_IN addr_clt = para_clt->addr_clt;
char buf_msg[MaxSize];
int res_val = 0;
while(true)
{
memset(buf_msg,0,MaxSize);
res_val = recv(sock_clt,buf_msg,MaxSize,0);
if(res_val < 0)
{
cout<<"Failed to receive message from client!Error code:"<<GetLastError()<<endl;
closesocket(sock_clt);
return;
}
else if(res_val == 0)
{
cout<<"Connect close..."<<endl;
break;
}
else
{
if(strcmp(buf_msg,"exit") == 0)
{
cout<<"Client requests to close the connection..."<<endl;
break;
}
cout<<inet_ntoa(addr_clt.sin_addr)<<" "<<ntohs(addr_clt.sin_port)<<":"<<buf_msg<<endl;
}
}
return;
}
在主函数调用Server类的WaitForClient()函数。
客户端
客户端头文件(client.h)
#ifndef CLIENT_H
#define CLIENT_H
#include<winsock2.h>
class Client
{
public:
Client();
~Client();
void Send();
private:
WORD winsock_ver;
WSADATA wsa_data;
SOCKET sock_clt;
SOCKADDR_IN addr_clt;
int res_val;
int addr_len;
};
#endif
客户端(client.cpp)
#include "client.h"
#include<iostream>
#include<winsock2.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define MaxSize 500
#define SER_PORT 8888
Client::Client()//构造函数
{
//初始化winsock
winsock_ver = MAKEWORD(2,2);
addr_len = sizeof(SOCKADDR_IN);
addr_clt.sin_family = AF_INET;
addr_clt.sin_port = htons(SER_PORT);
addr_clt.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
res_val = WSAStartup(winsock_ver,&wsa_data);
if(res_val != 0)
{
cout<<"WSAStartup error!"<<endl;
exit(1);
}
cout<<"WSAStartup successfully..."<<endl;
//创建socket
sock_clt = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sock_clt == INVALID_SOCKET)
{
cout<<"Failed to create client socket!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
//连接服务器
res_val = connect(sock_clt, (LPSOCKADDR)&addr_clt, addr_len);
if(res_val == SOCKET_ERROR)
{
cout<<"Failed to connect the server!Error code:"<<WSAGetLastError()<<endl;
WSACleanup();
exit(1);
}
cout<<"Client connect successfully!"<<endl;
}
Client::~Client()//析构函数
{
closesocket(sock_clt);
WSACleanup();
cout<<"client close..."<<endl;
}
void Client::Send()//实现对服务器端进行消息收发
{
char buf_msg[MaxSize];
int res_val = 0;
while(true)
{
memset(buf_msg,0,MaxSize);
cout<<"Send Message:";
cin>>buf_msg;
//发消息
res_val = send(sock_clt, buf_msg, sizeof(buf_msg), 0);
if(res_val == SOCKET_ERROR)
{
cout<<"Failed to send message to server!Error code:"<<WSAGetLastError()<<endl;
closesocket(sock_clt);
return;
}
}
return;
}
在主函数调用Client类的Send()函数。
过程实际和单线程的通信是一样的,详见:http://blog.csdn.net/x3i__x3i/article/details/79573209。不同在于服务器端需要通过创建线程来接收来自不同客户端的连接。