我一直在用C编写一个使用unix套接字和pthreads的小型多线程TCP服务器,但是我遇到了accept()的问题。它会挂起第二个请求,并且只有在先前线程退出时才会取消阻止。具有C套接字和pthreads的多线程TCP服务器 - 为什么accept()阻塞第二个请求?
下面是如何设置服务器套接字。
int server_start(server_t *server, int port) {
int fd;
struct sockaddr_in server_addr;
// Socket file descriptor.
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror("socket failed");
return 1;
}
// Socket address.
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
// Bind.
if (bind(fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
perror("bind failed");
return 1;
}
server->fd = fd;
listen(server->fd, server->clients_len);
pthread_create(&(server->thread), NULL, thread_entry_server, server);
return 0;
}
这是我的add_client代码。它为客户产生了一个单独的线程。
client_t *server_add_client(server_t *server) {
int iter,
fd,
status;
client_t *client;
printf("before\n");
fd = accept(server->fd, NULL, 0);
printf("after\n");
if (fd == -1) {
perror("accept");
return NULL; // Connection failed.
}
// Find an empty spot.
client = server->get_empty_spot();
client->fd = fd;
// Start the new thread.
status = pthread_create(
&(client->thread),
NULL,
thread_entry_client,
client
);
if (status != 0) {
perror("pthread_create");
close(client->fd);
return NULL;
}
client->active = 1;
return client;
}
这是我的客户端线程的入口函数:
void *thread_entry_client(void *void_client) {
client_t *client = void_client;
int len;
while (1) {
len = recv(client->fd, client->recv_buffer, RECV_BUFFER_LEN, 0);
if (len < 0) {
perror("recv");
client->active = 0;
close(client->fd);
return NULL;
}
if (len == 0) { // Client disconnected.
client->active = 0;
close(client->fd);
printf("disconnect\n");
return NULL;
}
if (len > 0) {
//printf("%s\n", client->recv_buffer);
printf("msg\n");
}
}
return NULL;
}
所以我在做什么测试,这是建立两个连接。第一个连接通过并且工作正常,但第二个连接不是 - 而是线程挂在accept()上。我知道这是从我的printfs(我留在那里)得知的,我知道在第一个客户端断开连接之后,accept()解除阻塞。我也知道我的代码没有关闭服务器套接字文件描述符或改变它。
上调试这有什么建议?我无法弄清楚。
编辑:这里是thread_entry_server。
void *thread_entry_server(void *void_server) {
server_t *server = void_server;
client_t *client;
while (1) {
client = server_add_client(server);
if (client == NULL) // Server is full or connection failed.
continue;
}
return NULL;
}
不应该'在pthread_create()''传递的server_add_client'代替'thread_entry_server'? – alk
哎呀,我忘了包含thread_entry_server。我会添加它。 –
在接收到传入的TCP连接之前,accept()将不会返回; connect()到accept()正在监听的端口是什么? –