Jump to content

    

IvanPletnev

Участник
  • Content Count

    48
  • Joined

  • Last visited

Community Reputation

0 Обычный

About IvanPletnev

  • Rank
    Участник

Recent Profile Visitors

701 profile views
  1. Да, именно так. Поэтому спасибо за наводку)
  2. Да, коллеги, это делается элементарно, оказывается. int optValue = 1; setsockopt(newconn, IPPROTO_TCP, TCP_NODELAY, (void*)&optValue, sizeof(optValue)); Работает идеально, я получил, что хотел.
  3. UDP тоже надо сделать. Позже займусь) А как определить текущий PCB для tcp_nagle_disable?
  4. Уважаемые коллеги, здравствуйте! Делаю устройство на STM32F427 с использованием LWIP Sockets. Отправляю в сокет пакеты длиной 9 байт с частотой 120Гц. На приёмной стороне среднее количество полученных девятибайтовых пакетов за секунду 120. То есть все пакеты доходят до адресата отлично. Но! Wireshark мне показывает вот такую картину. Он говорит, что за секунду отправляется 5 TCP пакетов с payload 216 байт. То есть 24 девятибайтовых посылки в одном пакете. Мне нужно передавать быстроменяющийся сигнал, и за 200мс он безнадежно устареет. Вопрос такой. Как сделать, чтобы LWIP старался отправить TCP пакет сразу, а не накапливал данные в буфере? Я понимаю, что такой подход неэффективен, но нужно именно так. Заранее благодарю за ответы.
  5. Уважаемые коллеги, не нашел на форуме ветки про ESP32, поэтому напишу здесь. Тем, кто изучает этот МК полезно будет это знать. Начал знакомиться с этим МК, запустил пример TCP сервера из комплекта SDK, всё работает замечательно. Решил пропинговать пакетами по 64 байта, заметил, что время пинга значительное - от 80 до 200мс. Начал изучать документацию, оказалось, что начиная с версии 3.1, по умолчанию стоит режим пониженного потребления (WIFI_PS_MIN_MODEM). Это значит, что в промежутке между маяками точки доступа WiFi спит. Чтобы включить нормальный режим, нужно вызвать функцию esp_wifi_set_ps(WIFI_PS_NONE); Время пинга теперь составляет от 2 до 5 мс. Пользуйтесь.
  6. Точно! Вы правы! У меня включен аппаратный расчет контрольных сумм. Я просто закомментировал функцию расчета контрольной суммы iecho->chksum = inet_chksum(iecho, len); и всё заработало!!!! Спасибо огромное!.
  7. Так, кое-что заработало. Теперь у меня отправляется один ICMP пакет тык. Но вылезла очередная проблема. Вот моя функция подготовки пакета: static void ping_prepare_echo(struct icmp_echo_hdr *iecho, u16_t len) { size_t i; size_t data_len = len - sizeof(struct icmp_echo_hdr); ICMPH_TYPE_SET(iecho, ICMP_ECHO); ICMPH_CODE_SET(iecho, 0); iecho->chksum = 0; iecho->id = PING_ID; iecho->seqno = htons(++ping_seq_num); /* fill the additional data buffer with some data */ for (i = 0; i < data_len; i++) { ((char*) iecho)[sizeof(struct icmp_echo_hdr) + i] = (char) i; } iecho->chksum = inet_chksum(iecho, len); } Wireshark говорит мне, что некорректная контрольная сумма. 0x0000 вместо 0x574e тык. Хотя контрольная сумма считается правильно и заносится в заголовок ICMP пакета тык. Все остальные поля структуры передаются правильно, а контрольная сумма при передаче куда-то исчезает. Видимо поэтому, когда я пытаюсь пинговать windows компьютер, он на этот пакет ничего не отвечает.
  8. Похоже, я нашел причину. В отладчике Atollic TrueStudio я обратил внимание на то, что задача виснет, когда в стеке находятся функции, отправляющие сообщения в очередь. Начал копать LWIP и обнаружил, что DEFAULT_RAW_RECVMBOX_SIZE в файле opt.h равен 0. Поэтому, наверное, задача и виснет. Пока не пробовал, но должно помочь.
  9. Уважаемые коллеги, здравствуйте! Столкнулся с такой проблемой. STM32F429, стек LWIP v.2.0.3, FreeRTOS. Пытаюсь создать сокет SOCK_RAW для периодического пинга подключенного клиента, он не создаётся. Причем, похоже, задача виснет, потому что диагностические сообщение не выводятся. При этом сокеты SOCK_STREAM и SOCK_DGRAM создаются без проблем. Кто-нибудь подскажет, куда копнуть? if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { puts("PING socket error"); return; } printf("Socket No %u created\r\n", s);
  10. Ну так можно посчитать клиентов, и если их больше заданного количества принудительно разрывать соединение, не создавая задач.
  11. Попробовал сделать так, через создание новых задач, работает отлично! Если от клиента мы получаем запрос на закрытие соединения (FIN), в задаче, в которой крутится функция recv, корректно закрываем сокет, удаляем созданные задачи. newconn = accept(sock, (struct sockaddr *)&remotehost, (socklen_t *)&size);//принимаем входящее подключение if ((newconn>1)||(newconn<1)){ close(newconn); } else if (newconn==1){ HAL_GPIO_WritePin(LD1_GPIO_Port,LD1_Pin, GPIO_PIN_SET); socketReceiveTaskHandle=sys_thread_new("sockRecvTask",socketReceiveTask,(void*)newconn,256,osPriorityNormal); socketSendTaskHandle=sys_thread_new("sockSendTask",socketSendTask,(void*)newconn,256,osPriorityNormal); } Еще нужно сделать, чтобы по прерыванию от PHY, сигнализирующему о какой-либо ошибке соединения, делалось тоже самое. Надо тестировать, конечно. Нет, в моём случае количество соединений ограничено, мне не нужно создавать много.
  12. На одном из форумов нашёл решение. После успешного accept создаётся задача, которой в качестве аргумента передаётся идентификатор сокета. И уже в этой задаче обрабатывается функция recv. Еще не пробовал, но, думаю, должно получиться.
  13. Доброго времени суток, уважаемые коллеги! Встала задача принимать пакеты из UART и передавать их в сеть. Запустил задачу-сервер на Socket API из примера ST, проверил, send - receive работает. Но когда дело дошло до реальной реализации, выяснилось, что функции accept и receive намертво блокируют задачу. Блокировку функцией accept решил вот такой нехитрой конструкцией: if (accept_state==0){ newconn = accept(sock, (struct sockaddr *)&remotehost, (socklen_t *)&size);//принимаем входящее подключение accept_state=1; } То есть, сервер принимает только одно входящее подключение. Общий вид главного цикла задачи-сервера: while (1) { if (accept_state==0){ newconn = accept(sock, (struct sockaddr *)&remotehost, (socklen_t *)&size);//принимаем входящее подключение accept_state=1; } event=osMessageGet(UART_RX_QHandle,10);//получаем указатель на структуру, которую нужно передать в сокет if (event.status==osEventMessage){ printf ("Queue received at %lu\r\n", osKernelSysTick()); pDataToSend=(UART_RX_Data*)event.value.v; HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin); send(newconn, pDataToSend->payload, pDataToSend->size, 0);//отправляем данные в сокет HAL_UART_Receive_IT(&huart3,uartRXBuffer,UART3RX_BUF_SIZE);//включаем приём в UART printf ("Switch context at %lu\r\n", osKernelSysTick()); osThreadYield(); } } в общем, циклично, по приходу пакета в UART, в задачу-сервер через очередь передается указатель на данные, которые нужно отправить в сокет. Вот теперь возникли два вопроса. Первый - как корректно завершить соединение по запросу от клиента? Попробовал сделать так: nbytes=recv(newconn, rxBuf, BUFLEN, MSG_PEEK); if (nbytes<=0){ close(newconn); } Сразу перестала работать очередь, потому что функция recv наглухо блокирует задачу. Что подскажете? И второй вопрос. Как отслеживать физический дисконнект? Может, кто уже решал эту задачу?
  14. Коллеги, вопрос закрыт. Оказывается, в сети 220В ноль был смещен относительно земли. Причем он двигался от 3 до 85 В RMS. Поэтому такая свистопляска и была. Запитали от нормального ввода и проблема решилась Всем спасибо за участие
  15. Посмотрел осциллографом сеть, синусоида ломаная вся, куча гармоник, из-за этого, наверное, это и происходит. Смещается минус питания. С заземленным минусом работает идеально. Я таких хороших показателей по шуму никогда не видел на этом аналого-цифровом устройстве.