PDA

Просмотр полной версии : ПЛК100 HTTP POST



PavelGO
25.09.2017, 16:15
Здравствуйте. Помогите советом, пожалуйста.
Удалённо: ПЛК - Роутер - (Инет) - Роутер - СерверАпач = Передача и прием работает.
Напрямую: ПЛК - СерверАпач = Постоянный ретрансмишн и до HTTP дело не доходит.
----------------------Wireshark--------------
172252 2513.393191 192.168.1.100 192.168.1.155 TCP 60 452 → 9908 [SYN] Seq=0 Win=512 Len=0
171975 2510.079455 192.168.1.100 192.168.1.155 TCP 60 [TCP Retransmission] 451 → 9908 [SYN] Seq=0 Win=512 Len=0
---------------------
Код взят с этого сайта:

network_counter:=network_counter+1;
IF network_counter > http_period THEN
network_counter:=0;
IF network_status <> 0 THEN
network_time_out:=network_time_out+1; (* счетчик таймаутов *)
out5:=FALSE;(*лампа связь выкл*)
END_IF

network_status:=1;
connect_counter:=0;
srv_adr.sin_addr:=IP_srv_16;
srv_adr.sin_family:=SOCKET_AF_INET;
srv_adr.sin_port:=STRING_TO_INT(PORT_srv_str);
IF sock>0 THEN SysSockClose(sock); END_IF;

END_IF

CASE network_status OF
1: (* создаём сокет *)
sock := SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_TCP);
IF sock<>16#FFFFFFFF THEN
network_status:=2;
SysSockIoctl(sock,SOCKET_FIONBIO,ADR(param_ctrl));
END_IF

2: (* коннектимся и сидим в этой ветке пару секунд пока не пройдёт коннект *)
IF connect_counter = 0 THEN
SysSockConnect(sock, ADR(srv_adr), SIZEOF(srv_adr));
END_IF;

connect_counter:=connect_counter+1;
IF connect_counter > connect_pause THEN
connect_counter:=0;
network_status:=3;
END_IF

3: (* посылаем запрос *)
GenPost(GenOutStringEnc());
sz_http_post_out:= LEN_string(http_post_out);
SysSockSend(sock, ADR(http_post_out),sz_http_post_out, SOCKET_MSG_OOB);

network_status:=4;

4: (* читаем сокет пока не встретим END *)
byte_r:=SysSockRecv(sock, ADR(http_otvet), 512, SOCKET_MSG_OOB);

IF FIND(http_otvet, 'END' ) > 0 THEN (* нашли END значит всё ок, ответ получили *)
network_status:=0;
http_otvet_prev:=http_otvet; (* сюда сохраняем ответ здесь будет блок его обработки*)
Explode(http_otvet_prev,15);
Command_executor();
out5:=TRUE;(*лампа связь есть вкл*)
p:=ADR(http_otvet);
FOR i:=0 TO 511 DO
p1:=p+i;
p1^:=0;
END_FOR
END_IF
END_CASE
RETURN;

capzap
25.09.2017, 17:27
в роутере случайно не настроен проброс портов на не стандартный порт?

PavelGO
25.09.2017, 18:55
Хм. В роли роутера керио и на него доступа у меня нет.проброс 9908 на 9908. Вопрос почему напрямую с вин7 не работать может транспортный? Обычно наоборот проблемы бывают. Завтра попробую другим компом на этот же порт.

PavelGO
26.09.2017, 10:45
route -f помог в итоге. Проблема решена, но...
Постоянно присутствует два сброса с предыдущего порта и ретрансмит(9 из 10 передач):
33291
Плк тут 1.100.
Получается нарушена последовательность закрытия соединения TCP:
ПЛК инициирует FIN и, не дождавшись ответа сервера, отбивает ответ на якобы FIN сервера, который приходит позже.
и интерфейс на последние два пакета отбивает RST.
Кривовата бибка или я туплю.
Попробую задержек понаставить.
Ретрансмит повержен таймерами:
33297
Но с FIN всё плохо.

SysSockIoctl(sock,SOCKET_FIONBIO,ADR(param_ctrl)); - Зачем?

Трофимов Артем
26.09.2017, 12:32
SysSockIoctl(sock,SOCKET_FIONBIO,ADR(param_ctrl)); - Зачем?

перевод работы сокета в неблокирующий режим. иначе при отсутсвии коннекта или передачи начнёт срабатывать watchdog контроллера и он будет перезагружаться.

PavelGO
28.09.2017, 16:00
Может у меня версия библиотеки 20.2.06 не подходит для прошивки 2.17 ПЛК100 ?

Филоненко Владислав
28.09.2017, 19:26
1. Необходимо добавлять в обмен heartbeat пакеты или просто обмен. Т.к. ПЛК устройство для урпавления в реальном времени, все таймауты обрыва очень маленькие.
2. Проверять коннект по таймауту не самая хорошая идея. Используйте, к примеру, попытку чтения и если в ответе не данные и код последней ошибки не "нет данных " - значит коннекта нет

PavelGO
28.09.2017, 20:36
Спасибо.
1.Понял (Или не до конца) Вас. Нужно постоянно сыпать пакетами для чего? Разжуйте, если можно?
2. Коннект переделаю.
Но как это поможет от RST? Проблема именно после закрытия сокета. Нарушена стандартная последовательность прощания.

PavelGO
18.10.2017, 19:56
Теперь с сегментированием [tcp segment of a reassembled pdu]. SysSockRecv пишет второй сегмент пакета снова по нулевому адресу http_otvet. Как бы обыграть приём таких пакетов? Если сегментов пару - покостылить можно, но в теории их может быть и больше. А если и порядок поступления сегментов нарушен(что разрешает протокол), то вообще беда.
А самое поганое в этом это длина данных=91. Первым 81, вторим пакетом доходят 10. Что то с апачем/cgi беда также.