Проект на базе FreeRTOS 7.2 + LwIP 1.3.2.
Реализован сервер на неблокирующих BSD-сокетах.
Сервер прекрасно работает с 1-2 клиентами. При попытке подключиться третьим клиентом, слушающий соккет не разблокирует задачу чтобы принять соединение, соответственно, подключение клиента игнорируется.
Код задачи сервера:
Код
static void server_socket_thread(void *arg)
{
uint32_t i, desc_ready, len_in = 0;
struct sockaddr_in address;
uint8_t close_conn;
uint8_t buffer[300];
int32_t new_sd, rc, err;
// Создаём слушающий соединения сокет
if ((NewConnSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return;
// Делаем сокет неблокирующим
err = 1;
err = lwip_ioctl(NewConnSock, FIONBIO, (char *)&err);
// Привязываем порт и ip к сокету
address.sin_family = AF_INET;
address.sin_port = htons(MODBUS_TCP_PORT);
address.sin_addr.s_addr = INADDR_ANY;
if (bind(NewConnSock, (struct sockaddr *)&address, sizeof (address)) < 0)
return;
// Преобразуем сокет в слушающий (TCP listen backlog = MAX_OPENED_SOCKETS)
listen(NewConnSock, MAX_OPENED_SOCKETS + 1);
// Initialize the master fd_set
FD_ZERO(&master_set);
max_sd = NewConnSock;
FD_SET(NewConnSock, &master_set);
do
{
// Copy the master fd_set over to the working fd_set.
memcpy(&working_set, &master_set, sizeof(master_set));
rc = select(max_sd + 1, &working_set, NULL, NULL, 0);
if (rc >= 0) // select() не рухнул
{
desc_ready = rc; // Кол-во готовых дескрипторов
for (i = 0; i <= max_sd && desc_ready > 0; ++i)
{
// Ищем всписке дескрипторов ожидающий обработки
if (FD_ISSET(i, &working_set))
{
desc_ready--; // Уменьшаем кол-во ожидающих дескрипторов
if (i == NewConnSock) // Если событие от слушающего сокета, создаём новый сокет для клиента
{
do
{
new_sd = accept(NewConnSock, NULL, NULL);
if (new_sd > 0)
{
FD_SET(new_sd, &master_set); // Добавляем новый дескриптор в список прослушиваемых
if (new_sd > max_sd)
max_sd = new_sd;
}
} while (new_sd != -1);
}
else // Событие не от сокета принимающего новые соединения (а от дочернего)
{
close_conn = 0;
do
{
rc = recv(i, buffer, sizeof(buffer), 0);
if (rc == 0) // Завершение соединения клиентом
{
close_conn = 1;
break;
}
len_in = rc;
// Обработка пакета от клиента
break;
} while (1);
if (close_conn)
{
close_conn = 0;
close(i);
FD_CLR(i, &master_set);
if (i == max_sd)
{
while (FD_ISSET(max_sd, &master_set) == 0)
max_sd -= 1;
}
}
}
}
}
}
} while (1);
}