ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Win32 Socket 使用

2026/8/24 0:43:24 拓冰建站 浏览量
Win32 Socket 使用

库说明

Win32 进行网络编程需要使用到 ws2_32.lib 库,它是 Windows Sockets 2 (Winsock2) 的库文件,其主要头文件为winsock2.h。如果使用 Windows.h 头文件则默认包含 winsock.h,他会和 winsock2.h 冲突。可以通过在包含 Windows.h 之前定义宏 WIN32_LEAN_AND_MEAN 来排除一些不常用的 Windows 头文件,这里面就会排除掉 winsock.h

// 链接 Winsock 库
#pragma comment(lib, "WS2_32.lib") //排除掉 Windows.h 中包含的一些不常用头文件
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

常用API

API说明参数
WSAStartup初始化WinSock库wVersionRequired:版本号,MAKEWORD(2, 2)表示2.2版本
lpWSAData:存储关于 Winsock 的信息
WSACleanup清理WinSock库
socket创建一个socketdomain:指定socket使用的地址族(AF_INET、AF_INET6等)
type:socket类型SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)等
protocol:使用的协议IPPROTO_TCP、IPPROTO_UDP,0表示自动选择
返回值:socket的文件描述符号
bind将socket与一个特定的地址和端口绑定sockfd:socket文件描述符
addr:包含地址信息的结构体的指针
addrlen:addr结构体长度
返回值:成功时返回 0,失败时返回 SOCKET_ERROR
listen将socket转换为监听状态sockfd:socket文件描述符
backlog:等待接受连接的客户端的最大数量,超过将被拒绝
accept接受客户端的连接请求,并创建一个新的套接字用于与客户端进行通信sockfd:socket文件描述符
addr:输出参数,用于纪录客户端的地址
addrlen:输出参数,表示addr的实际长度
返回值:返回一个新的套接字文件描述符,如果出现错误返回 SOCKET_ERROR
connect请求连接服务器s:标识要连接的 socket
name:服务器的地址信息
namelen:服务器地址信息结构体大小
send发送内容到sockets:socket文件描述符
buf:发送数据的缓冲区
len:需要发送字节数
flags:控制接收操作的行为,通常为 0
返回值:返回发送的字节数。如果出现错误,返回 SOCKET_ERROR
recv从已连接的socket接收数据sockfd:socket文件描述符
buf:接收数据的缓冲区
len:缓冲区大小,可以接收最大字节数
flags:控制接收操作的行为,通常为 0
返回值:返回接收的字节数。如果连接已关闭,返回 0。如果出现错误,返回 SOCKET_ERROR
closesocket关闭socket
inet_pton将点分十进制的IP转换为Long
它不是标准 Winsock 函数
它是在高版本中定义的
需要引用 Ws2tcpip.h 头文件
af:地址族(AF_INET、AF_INET6)
src:点分十进制字符串指针
转换后的二进制地址
inet_ntop将Long类型的IP转换为点分十进制
htons将16位主机字节序转换为网络字节序
网络字节序都采用大端字节序
用于端口号转换
htonl将32位主机字节序转换为网络字节序
网络字节序都采用大端字节序
用于IP转换

服务端

static DWORD WINAPI serverRecv(LPVOID lpParameter) {int* clientSocket = (int*)lpParameter;char readBuffer[512];while (true) {memset(readBuffer, 0, 512);int readSize = recv(*clientSocket, readBuffer, 512, 0);if (readSize <= 0) {perror("recv");closesocket(*clientSocket);return 0;}printf("read buffer = %s", readBuffer);}return 0;
}static DWORD WINAPI server(LPVOID lpParameter) {// 初始化 Winsock 2.2 版本WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {printf("Failed to initialize Winsock\n");}int serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (serverSocket == INVALID_SOCKET) {perror("socket");}sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;serverAddr.sin_port = htons(12345);if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {perror("bind");}if (listen(serverSocket, SOMAXCONN) == -1) {perror("listen");}while (TRUE) {sockaddr_in clientAddr;int* addrlen = NULL;int clientSocket = accept(serverSocket, (struct sockaddr*)&serverAddr, addrlen);if (clientSocket == -1) {perror("accept");continue;}CreateThread(NULL, 0, serverRecv, &clientSocket, 0, NULL);}return 0;
}

客户端

static DWORD WINAPI client(LPVOID lpParameter) {WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {printf("Failed to initialize Winsock\n");}printf("create client socket \n");int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (clientSocket == INVALID_SOCKET) {perror("socket");}sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(12345);inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {fprintf(stderr, "Failed to connect to server\n");}const char* message = "Hello, Server!";if (send(clientSocket, message, strlen(message), 0) == SOCKET_ERROR) {fprintf(stderr, "Failed to send data to server\n");}else {printf("Data sent to server: %s\n", message);}return 0;
}