编写支持多线程的基于windows socket的C语言程序,
时间: 2023-06-19 17:34:42 浏览: 140
以下是一个简单的基于 Windows Socket 的多线程 C 语言程序:
```c
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#define PORT 8080
#define MAX_CLIENTS 5
// 线程参数结构体
typedef struct {
SOCKET client_socket;
SOCKADDR_IN client_address;
} ThreadArgs;
// 线程函数
DWORD WINAPI handle_client(LPVOID lpParam) {
ThreadArgs *args = (ThreadArgs *)lpParam;
SOCKET client_socket = args->client_socket;
SOCKADDR_IN client_address = args->client_address;
char buffer[1024] = {0};
printf("Handling client %s:%d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
// 接受客户端消息并回复
while (1) {
int read_size = recv(client_socket, buffer, sizeof(buffer), 0);
if (read_size <= 0) {
// 客户端关闭连接或发生错误
break;
}
printf("Received message from client %s:%d: %s\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port), buffer);
send(client_socket, buffer, read_size, 0);
}
// 关闭连接
printf("Closing connection with client %s:%d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
closesocket(client_socket);
free(args);
return 0;
}
int main() {
WSADATA wsa_data;
SOCKET server_socket, client_socket;
SOCKADDR_IN server_address, client_address;
int client_address_size = sizeof(client_address);
DWORD thread_id;
// 初始化 Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) {
printf("WSAStartup failed\n");
return 1;
}
// 创建服务器套接字
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Failed to create server socket\n");
return 1;
}
// 绑定服务器地址和端口
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(PORT);
if (bind(server_socket, (SOCKADDR *)&server_address, sizeof(server_address)) == SOCKET_ERROR) {
printf("Failed to bind server socket\n");
return 1;
}
// 开始监听连接请求
if (listen(server_socket, MAX_CLIENTS) == SOCKET_ERROR) {
printf("Failed to listen for connections\n");
return 1;
}
printf("Listening on port %d...\n", PORT);
// 接受客户端连接并创建线程处理
while ((client_socket = accept(server_socket, (SOCKADDR *)&client_address, &client_address_size)) != INVALID_SOCKET) {
ThreadArgs *args = (ThreadArgs *)malloc(sizeof(ThreadArgs));
args->client_socket = client_socket;
args->client_address = client_address;
CreateThread(NULL, 0, handle_client, (LPVOID)args, 0, &thread_id);
}
// 关闭服务器套接字和 Winsock
closesocket(server_socket);
WSACleanup();
return 0;
}
```
在此示例中,我们使用了 Windows Socket 的 API 来创建服务器套接字、绑定地址和端口、监听连接请求、接受客户端连接,并在每个客户端连接上创建一个新的线程来处理消息收发。我们使用了 `CreateThread` 函数来创建新线程,并将客户端的套接字和地址作为参数传递给线程函数 `handle_client`。线程函数中,我们使用 `recv` 函数接受客户端的消息,并使用 `send` 函数回复相同的消息。如果客户端关闭连接或发生错误,我们将关闭连接并退出线程。注意,在此示例中我们并未处理多个客户端同时请求连接的情况,这可能会导致一些问题,例如有些客户端会因为连接超时而无法成功连接。为了处理此类情况,我们可以使用多线程或异步 I/O 来处理客户端连接。
阅读全文