#sockets #select #server
#сокеты #выберите #сервер
Вопрос:
Я новичок в программе сокетов. Я создал свою серверную программу с хорошим образцом программы, используя функцию выбора.
Он хорошо работает примерно с 20 000 подключений. Но в некоторых случаях соединение принимает двойное следствие без получения данных из первого сокета. Только данные, полученные от второго сокет-соединения. После этого первый ресурс сокета не может быть освобожден. FD_SET и FD_ISSET не работают с первым сокетом, если следствие примет, я думаю.
Рабочих клиентов 6.
Перед этой ситуацией примите, получите данные и закройте сокет, примите, данные rcv, закройте…
В этом случае примите, примите, получите данные из второго сокета и закройте второй сокет. Потеряно первое соединение с сокетом.
После этого примите назначение функции второго дескриптора сокета.
В чем проблема? Как можно освободить сокет fisrt?
БР Пол
Комментарии:
1. Это явно связано с ошибкой в вашем коде, но мы ее не видим. Пожалуйста, покажите фактический код, с которым у вас возникли проблемы.
Ответ №1:
Мой код выглядит следующим образом:
while(1)
{
//clear the socket set
FD_ZERO (amp;readfds);
//add master socket to set
FD_SET (sever_socket, amp;readfds);
max_sd = sever_socket;
//add child sockets to set
for ( i = 0 ; i < MAX_CLIENT ; i )
{
//socket descriptor
sd = client_socket [i];
//if valid socket descriptor then add to read list
if (sd > 0)
{
FD_SET( sd , amp;readfds);
}
//highest file descriptor number, need it for the select function
if(sd > max_sd)
{
max_sd = sd;
}
}
//wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely
activity = select ( max_sd 1 , amp;readfds , NULL , NULL , NULL);
if ((activity < 0) amp;amp; (errno!=EINTR))
{
LOG_F (WARNING, "select error");
}
//If something happened on the master socket, then its an incoming connection
if (FD_ISSET(sever_socket, amp;readfds))
{
if ((new_socket = accept (sever_socket, (struct sockaddr *) amp;address, (socklen_t*) amp;addrlen)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//inform user of socket number - used in send and receive commands
LOG_F (INFO, "New connection, socket fd is %d, ip is : %s, port : %d",
new_socket, inet_ntoa(address.sin_addr), ntohs(address.sin_port));
//add new socket to array of sockets
for (i = 0; i < MAX_CLIENT; i )
{
//if position is empty
if( client_socket[i] == 0 )
{
client_socket[i] = new_socket;
LOG_F (INFO, "Adding to list of sockets as %d" , i);
break;
}
}
}
for (i = 0; i < MAX_CLIENT; i )
{
sd = client_socket[i];
if (FD_ISSET (sd , amp;readfds))
{
memset (amp;rcvBuf, 0x00, sizeof(rcvBuf));
if ((fp = fdopen (sd, "r")) == NULL)
{
LOG_F (WARNING, "TCP_SOCKET FD_OPEN Error");
close (sd);
client_socket[i] = 0;
}
else
{
ret = ioctl (sd, FIONREAD, amp;nread);
if (nread == 0)
{
fclose (fp);
close (sd);
client_socket[i] = 0;
LOG_F (WARNING, "Client disconnected(as %d, fd %d)", i, sd);
}
else
{
len = recv (sd, rcvBuf, nread, 0);
if (len > 0)
{
LOG_F (INFO, "RECV size %d" , len);
...
do_msg_handler ()
}
}
...