简单的客户端-服务器模型
1、服务器端代码
1 #pragma comment(lib, "ws2_32.lib") 2 3 #include <WinSock2.h> 4 #include <iostream> 5 6 using namespace std; 7 8 bool LoadSockLib() 9 { 10 WSADATA wsaData; 11 if(SOCKET_ERROR == WSAStartup(MAKEWORD(2, 2), &wsaData)) 12 { 13 DWORD dwError(0); 14 dwError = GetLastError(); 15 cout << "加载套接字库失败,错误代码:" << dwError << endl; 16 return false; 17 } 18 return true; 19 } 20 21 int main() 22 { 23 if(!LoadSockLib()) 24 { 25 exit(-1); 26 } 27 28 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); 29 if(INVALID_SOCKET == sock) 30 { 31 DWORD dwError(0); 32 dwError = GetLastError(); 33 cout << "获取套接字失败,错误代码:" << dwError << endl; 34 exit(-2); 35 } 36 37 sockaddr_in addrBind; 38 addrBind.sin_family = AF_INET; 39 addrBind.sin_port = htons(3456); 40 addrBind.sin_addr.S_un.S_addr = INADDR_ANY; 41 42 sockaddr_in addrClient; 43 44 int iRetVal = 0; 45 if(iRetVal = bind(sock, (sockaddr*)&addrBind, sizeof(addrBind))) 46 { 47 DWORD dwError(0); 48 dwError = GetLastError(); 49 cout << "绑定套接字失败,错误代码:" << dwError << endl; 50 exit(-3); 51 } 52 53 listen(sock, 5); 54 int len = sizeof(sockaddr); 55 cout << "服务器已经准备好,正在等待客户端的连接..." << endl; 56 SOCKET sockClient = accept(sock, (sockaddr*)&addrClient, &len); 57 cout << inet_ntoa(addrClient.sin_addr) << "已连接。" << endl; 58 59 char szRecBuf[512] = {0}; 60 char szSendBuf[512] = {0}; 61 while(true) 62 { 63 cout << "请给客户端发送消息:" << endl; 64 cin >> szSendBuf; 65 send(sockClient, szSendBuf, strlen(szSendBuf), 0); 66 cout << "消息已经发送给客户端,等待其回复..." << endl; 67 68 iRetVal = recv(sockClient, szRecBuf, 512, 0); 69 cout << "127.0.0.1 回复说:" << szRecBuf << endl; 70 71 memset(szRecBuf, 0, 512); 72 memset(szSendBuf, 0, 512); 73 } 74 75 return 0; 76 }
2、客户端代码
1 #pragma comment(lib, "ws2_32.lib") 2 3 #include <WinSock2.h> 4 #include <iostream> 5 6 using namespace std; 7 8 bool LoadSockLib() 9 { 10 WSADATA wsaData; 11 if(SOCKET_ERROR == WSAStartup(MAKEWORD(2, 2), &wsaData)) 12 { 13 DWORD dwError(0); 14 dwError = GetLastError(); 15 cout << "加载套接字库失败,错误代码:" << dwError << endl; 16 return false; 17 } 18 return true; 19 } 20 21 int main() 22 { 23 if(!LoadSockLib()) 24 { 25 exit(-1); 26 } 27 28 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); 29 if(INVALID_SOCKET == sock) 30 { 31 DWORD dwError(0); 32 dwError = GetLastError(); 33 cout << "获取套接字失败,错误代码:" << dwError << endl; 34 exit(-2); 35 } 36 37 SOCKADDR_IN addr; 38 addr.sin_family = AF_INET; 39 addr.sin_port = htons(3456); 40 addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 41 42 int iRetVal = 0; 43 iRetVal = connect(sock, (SOCKADDR*)&addr, sizeof(addr)); 44 if(SOCKET_ERROR == iRetVal) 45 { 46 DWORD dwError(0); 47 dwError = GetLastError(); 48 cout << "连接服务器失败,错误代码:" << dwError << endl; 49 exit(-3); 50 } 51 52 char szRecBuf[512] = {0}; 53 char szSendBuf[512] = {0}; 54 while(true) 55 { 56 cout << "等待服务器发送消息..." << endl; 57 iRetVal = recv(sock, szRecBuf, 512, 0); 58 cout << "127.0.0.1 说:" << szRecBuf << endl; 59 60 cout << "请回复服务器:" << endl; 61 cin >> szSendBuf; 62 send(sock, szSendBuf, strlen(szSendBuf), 0); 63 64 memset(szRecBuf, 0, 512); 65 memset(szSendBuf, 0, 512); 66 } 67 return 0; 68 }
执行结果:
服务器端
客户端
3、我的疑问
虽然程序是正确的执行的了,但是其中却还有存有许多的疑问。
1. 以前看书时,说的是,服务器端监听一个固定的端口,当收到连接请求时,用accept接受请求并返回一个新生成的套接字,该服务器套接字继续监听该固定端口。于是问题来,我运行该程序,当服务器端进行通信时,我用netstat查看了一下端口,发现监听的是3456(我指定的监听端口),其状态为listen,然而,通信的端口还是3456,也就是服务器和客户端通信使用的端口还是3456,因为我现在一个客户端,所以没问题,但是,将程序的监听功能放在一个单独的线程中执行的话,那么就可以同时和多个客户端通信,那难熬还是使用同一个端口么?下面是我查看端口的截图
未完待续。。。