参考了: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。不同在于服务器端需要通过创建线程来接收来自不同客户端的连接。
