TCP协议(三)之Windows实现
tcp 编程一般的步骤:
server(服务端)
1.new 个 socket
2.bind (IP,port)
3.listen,等待客户端的连接
4.accept 接受客户端的连接
5.接收(recv) 发送数据(send)
6.关闭连接
client(客户端)
1.new 个 socket
2.bind(ip,port)
3.connect (server.ip,server,port)
4.recv() /send()
5.关闭连接
2.程序
服务器程序
#include <stdlib.h> #include <stdio.h> #include <WinSock2.h> #pragma comment(lib,"Ws2_32.lib ") int main() { WSADATA wsaData; struct sockaddr_in servAddr; struct sockaddr_in cliAddr; if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { printf("Error:RequestWindowsSocketLibrary failed!\n"); return 0; } /* 设置IP地址 */ memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //绑定本机IP //servAddr.sin_addr.s_addr = inet_addr("192.168.1.53"); /* 设置端口 */ servAddr.sin_family = AF_INET; servAddr.sin_port = htons(3000); //端口为3000 /* 创建套接服务字 */ SOCKET serverSocket; serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == INVALID_SOCKET) { printf("Error:CreatServerSocket failed!\n"); return 0; } /* 绑定服务器套接字 */ if (bind(serverSocket, (sockaddr*)&servAddr, sizeof(sockaddr)) == SOCKET_ERROR) { printf("ERROR:Bind failed!\n"); return 0; } /* 监听端口 */ if (listen(serverSocket, 20) == SOCKET_ERROR) { closesocket(serverSocket); WSACleanup(); printf("ERROR:Listen failed!\n"); return 0; } printf("linstening:%dport...\n", ntohs(servAddr.sin_port)); /* 阻塞方式等待accept */ int len = sizeof(cliAddr); SOCKET clientSocket; clientSocket = accept(serverSocket, (sockaddr*)&cliAddr, &len); printf("Connected:%s \r\n", inet_ntoa(cliAddr.sin_addr)); /* 接受消息 */ char recvBuf[100] = { 0 }; recv(clientSocket, recvBuf, sizeof(recvBuf), 0); /* 发送消息 */ send(clientSocket, recvBuf, 100, NULL); closesocket(clientSocket); WSACleanup(); system("pause"); return 1; }
客户端代码
#include "stdlib.h" #include <stdio.h> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll int main() { //初始化DLL //主版本号(低字节)为2,副版本号为2,返回 0x0202 WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; //WSAStartup() 函数执行成功后,会将与 ws2_32.dll 有关的信息写入 WSAData 结构体变量 //(只需关注前两个成员即可) if (WSAStartup(sockVersion, &wsaData) != 0) return 0; //创建套接字,socket() 函数用来创建套接字,确定套接字的各种属性 //IPv4 地址、面向连接的数据传输方式、TCP 传输协议 SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //向服务器发起请求,将创建的套接字与IP地址 101.76.220.219、端口 3000 绑定: sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_family = PF_INET; //32位IP地址,s_addr 是一个整数(unsigned long),而IP地址是一个字符串, //所以需要 inet_addr() 函数进行转换 sockAddr.sin_addr.s_addr = inet_addr("101.76.218.229"); //16位的端口号,端口号需要用 htons() 函数转换,0~1023 的端口一般由系统分配给特定的服务程序, //尽量在 1024~65536 之间分配端口号。 sockAddr.sin_port = htons(3000); //强制类型转换,服务器端要用 bind() 函数将套接字与特定的IP地址和端口绑定起来, //只有这样,流经该IP地址和端口的数据才能交给套接字处理 while (connect(sock, (SOCKADDR*)& sockAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) { printf("连接失败\n"); Sleep(1000); } printf("成功连接到服务器!\n"); char sendBuf[100] = {"Hello World"}; send(sock, sendBuf, 100, NULL); char recvBuf[100] = { 0 }; recv(sock, recvBuf, 100, 0); closesocket(sock); WSACleanup(); for (int i = 0; i < 12; i++) { printf("%c",recvBuf[i]); } system("pause"); return 1; }