今天我將分享socket編程,在這條路上的坑,我還能剩多少了!linux
以前再linux系統下進行學習,今天嘗試再window下進行編程;ios
區別:後者須要在進行socket編程,加載socket連接庫。編程
server端:數組
#include<iostream> #include<string> #include<stdlib.h> using namespace std; #include<WinSock2.h> #include<Ws2tcpip.h> #pragma comment(lib,"ws2_32.lib") #define CONNECT_NUM_MAX 10 //最大鏈接數 #define MSG_MAX_NUM 256 //接受最大數據數 #define MY_PORT 18000 //端口 #define MY_IP 127.0.0.1 //IP int main() { //0.加載套接字庫 WSADATA wsaData; int ret = 0; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) { cout << "WSAStartup(MAKEWORD(2, 2) execute failed!" << endl; return -1; } if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion)) { WSACleanup(); cout << "WSADATA version is not correct" << endl; return -1; } //1.建立套接字 SOCKET sockSer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockSer == INVALID_SOCKET) { cout << "sockSer create fail" << endl; return -1; } //初始化服務器地址族變量 sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(18000); serAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); int serLen = sizeof(SOCKADDR); //2.bind連接 ret = bind(sockSer, (sockaddr *)&serAddr, serLen); if (ret == SOCKET_ERROR) { cout << "bind execute fail" << endl; closesocket(sockSer); WSACleanup(); return -1; } //3.listen監聽 ret = listen(sockSer, CONNECT_NUM_MAX); if (ret == SOCKET_ERROR) { cout << "listen execute failed" << endl; closesocket(sockSer); return -1; } else { cout << "Server is listening on" << serAddr.sin_addr.s_addr << ":" << serAddr.sin_port << "." << endl; } //4.accept sockaddr_in cliAddr; int cliLen = sizeof(SOCKADDR); SOCKET sockCli = accept(sockSer, (sockaddr *)&cliAddr, &cliLen); if (sockCli == INVALID_SOCKET) { cout << "Accepted failed with error code:%d\n" << WSAGetLastError() << endl;; closesocket(sockSer); WSACleanup(); return -1; } cout << "Accepted\n" ; //5.recv/send char sendMsg[MSG_MAX_NUM]; char recvMsg[MSG_MAX_NUM]; while (1) { ZeroMemory(recvMsg, MSG_MAX_NUM); //對數組進行初始化 recv(sockCli, recvMsg, 256,0); cout <<"Cli:>"<<recvMsg << endl; ZeroMemory(sendMsg, MSG_MAX_NUM); cout << "Ser:>"; cin >> sendMsg; send(sockCli, sendMsg, strlen(sendMsg)+1, 0); } //6.close closesocket(sockSer); return 0; }
坑1:在服務端,咱們須要兩個SOCKET對象(sockSer和sockCli),前者用來鏈接、監聽和接受客戶端請求;後者則在服務端接受客戶端請求後返回的sockCli,做爲在收發消息的第一個參數。服務器
坑2:必須將客戶端和服務器的端口好進行統一。socket
坑3:sockaddr_in 建立的結構體變量,在配置完成後,connect函數中使用須要進行強轉(sockaddr *).tcp
客戶端:函數
#include<iostream> #include<string> #include<stdlib.h> using namespace std; #include<WinSock2.h> #include<Ws2tcpip.h> #pragma comment(lib,"ws2_32.lib") #define MSG_MAX_NUM 256 #define MY_IP 127.0.0.1 #define MY_PORT 18000 int main() { //0.加載套接字庫 WSADATA wsaData; int ret = 0; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) { cout << "WSAStartup(MAKEWORD(2, 2), &wsaData) execute failed" << endl; return -1; } if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion)) { WSACleanup(); cout << "WSADATA version is not correct" << endl; return -1; } //1.建立套接字 SOCKET sockCli = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockCli == INVALID_SOCKET) { cout << "sockCli create failed" << endl; } //初始化客戶端連接服務器端變量 sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(MY_PORT); serAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int serLen = sizeof(sockaddr); //2.connect ret = connect(sockCli, (sockaddr *)&serAddr, serLen); if (ret != 0) { cout << "connect failed" << endl; closesocket(sockCli); WSACleanup(); cin.get(); return -1; } //3.收發消息 char sendMsg[MSG_MAX_NUM]; char recvMsg[MSG_MAX_NUM]; while (1) { ZeroMemory(sendMsg, MSG_MAX_NUM); cout << "Cli:>"; cin >> sendMsg; send(sockCli, sendMsg, strlen(sendMsg) + 1, 0); ZeroMemory(recvMsg, MSG_MAX_NUM); recv(sockCli, recvMsg, 256, 0); cout << "Ser:>" << recvMsg << endl; } //4.關閉套接字 closesocket(sockCli); return 0; }
坑1:客戶端只要一個SOCKET對象,即針對服務端進行鏈接,發送數據;學習
坑2:sockaddr_in 建立的結構體變量,在配置完成後,connect函數中使用須要進行強轉(sockaddr *).大數據