今天我将分享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 *).大数据