Я писал небольшой многопоточный TCP-сервер в C, используя unix-сокеты и pthreads, но у меня возникают проблемы с accept(). Он зависает во втором запросе, который приходит, и только разблокируется, когда предыдущий поток завершается.Многопоточный TCP-сервер с C-сокетами и pthreads - Почему 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() разблокирует ПОСЛЕ того, как первый клиент отключится. Я также знаю, что мой код не закрывает дескриптор файла сокета сервера или не меняет его.
Любые советы по отладке? Я не могу понять.
EDIT: Здесь находится 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()' pass 'server_add_client' вместо' thread_entry_server'? – alk
Упс, я забыл включить thread_entry_server. Я добавлю. –
accept() не возвращается, пока не будет получено входящее TCP-соединение; что такое connect() для порта, который принимает accept()? –