Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сервер на неблокирующих сокетах
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > Fast Ethernet/Gigabit Ethernet/FibreChannel
athlon64
Проект на базе 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);
}
athlon64
Нашёл константу NUM_SOCKETS, которая переопредлена константой MEMP_NUM_NETCONN, которая задаёт размер массива sockets и по-умолчанию равна 4.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.