Вход

Просмотр полной версии : tcp socket



nekain
07.04.2022, 12:06
Доброго времени суток. Нужна помощь в наладке сокетного приложения.
При получении сообщения от клиента (plc) к серверу (pc) получаю это сообщение и часть прошлого сообщения

Например, если отправляю "OK", а получаю "OKate,791212,1000,982"

Также вот мой клиент

CASE eState OF


CLIENT_STATE_CREATE:
hClientSocket := SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_TCP);
IF hClientSocket <> SOCKET_INVALID THEN
eState := CLIENT_STATE_CONNECT;
ELSE
eState := CLIENT_STATE_CLOSE;
END_IF

CLIENT_STATE_CONNECT:

stClientSettings.sin_family := SOCKET_AF_INET;
stClientSettings.sin_port := wPort;
dwIPaddr := IP_DECODE(sIPv4);
stClientSettings.sin_addr := dwIPaddr;
SysSockConnect(hClientSocket, ADR(stClientSettings), SIZEOF(stClientSettings) );
eState := CLIENT_STATE_SENDING;


CLIENT_STATE_SENDING:
IF SCREEN = 7 THEN
IF check = 200 OR check = 1 THEN
sSendToServer := CONCAT('insert,',DWORD_TO_STRING(number_filter));
OLD_FILTER := number_filter;
IF sReadFromServer = 'Ok / Insert' OR sReadFromServer = 'Ok / Update' THEN
sSendToServer := CONCAT('update,',DWORD_TO_STRING(number_filter));
END_IF
sSendToServer := CONCAT(sSendToServer, ',');
sSendToServer := CONCAT(sSendToServer, INT_TO_STRING(count_filter));
sSendToServer := CONCAT(sSendToServer, ',');
sSendToServer := CONCAT(sSendToServer, INT_TO_STRING(succses_filter));
END_IF
ELSE
sSendToServer := 'OK';
END_IF
diSendBytes := SysSockSend(hClientSocket, ADR(sSendToServer), LEN(sSendToServer), c_diFlag);
IF diSendBytes <> SIZEOF(sSendToServer) THEN
eState := CLIENT_STATE_READ;
fbTon(IN := FALSE);
ELSE
fbTon(IN := TRUE, PT := tSendServer);
IF fbTon.Q THEN
eState := CLIENT_STATE_CLOSE;
fbTon(IN := FALSE);
END_IF
END_IF

CLIENT_STATE_READ:

diRecvBytes := SysSockRecv(hClientSocket, ADR(sReadFromServer), SIZEOF(sReadFromServer), c_diFlag);
FIND('Close', sReadFromServer);
IF IS_CC(sReadFromServer, 'Close') THEN
%QW8.1.9.0 := 1;
ELSE
%QW8.1.9.0 := 0;
END_IF
IF diRecvBytes = SIZEOF(sReadFromServer) THEN
eState := CLIENT_STATE_CLOSE;
fbTon(IN := FALSE);
ELSE
fbTon(IN := TRUE, PT := tRecvServer);
IF fbTon.Q THEN
eState := CLIENT_STATE_CLOSE;
fbTon(IN := FALSE);

END_IF
END_IF

CLIENT_STATE_CLOSE:

SysSockShutdown(hClientSocket, c_diHow);
fbTon(IN := TRUE, PT := tSockClose);
IF fbTon.Q THEN
SysSockClose(hClientSocket);
eState := CLIENT_STATE_CREATE;
fbTon(IN := FALSE);
END_IF

END_CASE

Евгений Кислов
07.04.2022, 12:28
Добрый день.
Вы ваш приемный буфер (sReadFromServer) нигде не очищаете между чтением.

nekain
08.04.2022, 03:55
Ему присвоить пустое значение или возможно какой-то функцией очистить буфер?

Евгений Кислов
08.04.2022, 06:16
Ему присвоить пустое значение или возможно какой-то функцией очистить буфер?

Присвоение пустого значения не подойдет.
Используйте функцию SysMemSet из библиотеки SysLibMem.

capzap
08.04.2022, 07:23
Ему присвоить пустое значение или возможно какой-то функцией очистить буфер?



VAR
sReadFromServer : ARRAY[0..15] OF BYTE;
END_VAR
VAR CONSTANT
clearReadServer : ARRAY[0..15] OF BYTE;
END_VAR
...
(* BEGIN *)
(* какие то действия по принятому буферу и далее *)
sReadFromServer := clearReadServer;




ЗЫ если переменная это строка, то просто sReadFromServer := '';

ВладОвен
16.05.2022, 10:47
Всем привет, подскажите, почему не получается принять строку от сервера.
Отправляю на сервер строку и жду от него ответа. После этого подключение закрываю. Наблюдаю за обменом через программу WireShark.
Эта программа показывает, что сервер ответил на мой запрос. И длина ответа 150 байт.
60675

В CodeSys для тестирования использую Control Win V3. Вижу, что пришло 150 байт, но почему они не падают в строку?
60676

В программе клиента есть переменная eState - это для создания очередности работы с сервером (create, connect, send, receive, close).
А переменная tries - для ограничения максимальных попыток в каждом шаге. Т.е. если более 10 попыток, то переходим в режим close.
Пробовал на реальном ПЛК - результат тот же.
Что я делаю не так?

ВладОвен
16.05.2022, 11:46
Я не указывал это. Объявил просто string. И для отправки и для приема.

UPD: Действительно - при указании длины строки прием идет нормально:

60679

Хорошо. А тогда еще вопрос:
В боевом режиме нужно будет отправить данные, размером около 8-10Кбайт за один обмен. Это нужно реализовывать тоже через строку? Или уже применять массив?

capzap
16.05.2022, 11:48
может поэтому 150 символов не помещается в объект размером 80 символов, проверите