我一直在用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()正在監聽的端口是什麼? –