CODESYS форум

Добро пожаловать на официальный форум CODESYS
Deutsche Version English version russian version 
Текущее время: Чт окт 19, 2017 9:56 am

Часовой пояс: UTC+01:00




Начать новую тему  Ответить на тему  [ 22 сообщения ]  На страницу 1 2 След.
Автор Сообщение
 Заголовок сообщения: странная работа SysSockRecv
СообщениеДобавлено: Пн июл 16, 2012 9:02 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
Итак, сервер отправляет 5 байт клиенту, клиент получает эти данные полностью(в массиве, который указан в recv данные видны в отладчике Codesys), но как результат Recv выдает не количество полученный байт(5), а значение ошибки(-1), с чем это может быть связано?
Код:
PROGRAM PLC_PRG
VAR
   mySocket:DINT;
   tempArr:ARRAY [0..4] OF BYTE;
   answerArr:ARRAY [0..1024] OF BYTE;
   ans_pointer:POINTER TO BYTE;
   i:DINT;
   j:DINT;
   myConnect:CONNECT_TO_SERVER;
   myQuery:QUERY_TO_SERVER;
   myAnswer:GET_INFO_FROM_SERVER;
   start:BOOL;
   con:BOOL;
END_VAR

IF start THEN
myConnect(port_in:=3490 , addr_in:='192.168.100.1' , socket=> mySocket);
FOR i:=0 TO 4 DO
   tempArr[i]:=DINT_TO_BYTE(i+1);
END_FOR
myQuery(query_pointer:=ADR(tempArr) , len_query:=i , socket:=mySocket , res_bytes=> j);
ans_pointer:=ADR(answerArr);
myAnswer(socket:=mySocket , answer_pointer:=ans_pointer , read_bytes=>j );
con:=UNCONNECT_TO_SERVER(mySocket);
start:=FALSE;
END_IF


Send работает корректно, возвращает количество переданных на сервер байт

Функциональный блок myAnswer:
Код:
FUNCTION_BLOCK GET_INFO_FROM_SERVER
(*
ïîëó÷åíèå èíôîðìàöèè îò ñåðâåðà
Result=-1, åñëè îøèáêà ïðè ïåðåäà÷å èíôîðìàöèè
Result=0, åñëè ñîåäèíåíèå çàêðûòî ñåðâåðîì
Result=any other number (êîëè÷åñòâî ïåðåäàííû áàéò)
*)
VAR_INPUT
   socket:DINT;                        (*äåñêðèïòîð ñîêåòà*)
   answer_pointer:POINTER TO BYTE;      (*ìàññèâ áàéò - îòâåò ñåðâåðà*)
END_VAR
VAR_OUTPUT
   read_bytes:DINT;                     (*êîëè÷åñòâî ïîëó÷åííûõ áàéò*)
END_VAR
VAR
   size_buf:DINT:=1024;                  (*ðàçìåð áóôåðà äëÿ îòâåòà*)
END_VAR

read_bytes:=SysSockRecv(socket,answer_pointer,size_buf,0);


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Вт июл 24, 2012 10:08 am 
Не в сети

Зарегистрирован: Вт сен 15, 2009 7:48 am
Сообщения: 47
Плк какой?


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Ср июл 25, 2012 6:27 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
Mikhail Shvetsov писал(а):
Плк какой?

beck dk55


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Ср июл 25, 2012 1:11 pm 
Не в сети

Зарегистрирован: Вт сен 15, 2009 7:48 am
Сообщения: 47
Сие странно. -1 обычно связанно с внутренними проблемами функции которые ведут к ее крэшу. В данном случае прием идет и выдает ошибку непредвиденной ситуации- странно. Я смогу потестировать этот чип 2 августа


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Чт июл 26, 2012 5:40 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
Mikhail Shvetsov писал(а):
Сие странно. -1 обычно связанно с внутренними проблемами функции которые ведут к ее крэшу. В данном случае прием идет и выдает ошибку непредвиденной ситуации- странно. Я смогу потестировать этот чип 2 августа

благодарю, подождем до 2 августа


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Пт июл 27, 2012 7:53 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
Попробовал добавить проверку на готовность сокета на чтение/запись с помощью select-а, однако проверка select-ом проходит, но результаты те же: send - все корректно, recv = -1, но данные приняты.

Уважаемый, Mikhail Shvetsov, не могли бы вы протестировать мой код 2 августа.

Прикладываю код, который у меня сейчас и проект сервера с которым тестирую(VS2010):
RLC_PRG:
Код:
IF start THEN
   mySocket:=SysSockCreate(SOCKET_AF_INET,SOCKET_STREAM, SOCKET_IPPROTO_TCP);
   SET_TIME_OUT_SOCKET(mySocket,500000,0);
   IF CONNECT_SERVER(3490, '192.168.100.1', mySocket) THEN
      j:=TCP_GET_INFO(mySocket, ADR(answerArr));
      i:=TCP_SEND_INFO(ADR(answerArr), 4, mySocket);
   END_IF
   con:=SysSockClose(mySocket);
   start:=FALSE;
END_IF

SET_TIME_OUT_SOCKET
Код:
FUNCTION SET_TIME_OUT_SOCKET : BOOL
(*
óñòàíîâêà òàéìàóòà äëÿ ñîêåòà
Result=true, ïðè óñïåõå
Result=false, ïðè îøèáêå
*)
VAR_INPUT
   socket:DINT;
   usec:DINT;
   sec:DINT;
END_VAR
VAR
   time_var:SOCKET_TIMEVAL;
   result:BOOL;
END_VAR

result:=FALSE;
IF sec<>0 AND usec<>0 THEN
      time_var.tv_sec:=sec;
      time_var.tv_usec:=usec;
      result:=SysSockSetOption(
         socket,
         SOCKET_SOL,
         SOCKET_SO_SNDTIMEO,
         ADR(time_var),
         SIZEOF(time_var));
      IF result=TRUE THEN
         result:=SysSockSetOption(
            socket,
            SOCKET_SOL,
            SOCKET_SO_RCVTIMEO,
            ADR(time_var),
            SIZEOF(time_var));
      END_IF
END_IF
SET_TIME_OUT_SOCKET:=result;

CONNECT_SERVER
Код:
FUNCTION CONNECT_SERVER : BOOL
(*
ïîäêëþ÷åíèå ê ñåðâåðó
Result=false, åñëè îøèáêà ïðè ïîäêëþ÷åíèè  ê ñåðâåðó
Result=true ïðè óñïåøíîì ïîäêëþ÷åíèè ê ñåðâåðó
*)
VAR_INPUT
   port_in:UINT;            (*ïîðò ñåðâåðà*)
   addr_in:STRING(80);      (*ip-àäðåñ ñåðâåðà*)
   socket:DINT;            (*äåñêðèïòîð ñîêåòà*)
END_VAR
VAR
   serv_addr: SOCKADDRESS;
   i:INT;
END_VAR

IF socket<>SOCKET_INVALID THEN
   (*ïîäêëþ÷åíèå ê ñåðâåðó*)
   serv_addr.sin_family:=SOCKET_AF_INET;
   serv_addr.sin_port:=SysSockHtons(port_in);
   serv_addr.sin_addr:=SysSockInetAddr(addr_in);
   FOR i:=0 TO 7 BY 1 DO
      serv_addr.sin_zero[i]:=0;
   END_FOR
   IF NOT(SysSockConnect(socket,ADR(serv_addr),SIZEOF(serv_addr))) THEN
      CONNECT_SERVER:=FALSE;
   ELSE
      CONNECT_SERVER:=TRUE;
   END_IF
END_IF

TCP_GET_INFO
Код:
Result=-1, åñëè îøèáêà ïðè ïåðåäà÷å èíôîðìàöèè
Result=0, åñëè ñîåäèíåíèå çàêðûòî ñåðâåðîì
Result=any other number (êîëè÷åñòâî ïåðåäàííûõ áàéò)
*)
VAR_INPUT
   socket:DINT;                        (*äåñêðèïòîð ñîêåòà*)
   answer_pointer:DWORD;      (*ìàññèâ áàéò - îòâåò ñåðâåðà*)
END_VAR
VAR
   fdRead:SOCKET_FD_SET;
   tvTimeout:SOCKET_TIMEVAL;
   err: DINT;
END_VAR

tvTimeout.tv_sec := 0 ;
tvTimeout.tv_usec := 50000;
fdRead.fd_count := 1;
fdRead.fd_array[0] := socket;
SysSockSelect(SOCKET_FD_SETSIZE, ADR(fdRead), 0, 0, ADR(tvTimeout));
IF fdRead.fd_array[0]=socket THEN
   TCP_GET_INFO:=SysSockRecv(socket, answer_pointer, SIZE_BUF, 0);
ELSE TCP_GET_INFO:=-1;
END_IF

TCP_SEND_INFO
Код:
FUNCTION TCP_SEND_INFO : DINT
(*
îòïðàâëÿåò òåêñò çàïðîñà íà ñåðâåð
Result=-1, åñëè îøèáêà ïðè ïåðåäà÷å çàïðîñà
Result=0, åñëè ñîåäèíåíèå çàêðûòî
Result=any other number(åîëè÷åñòâî ïåðåäàííûõ áàéò)
*)
VAR_INPUT
   query_pointer:POINTER TO BYTE;      (*ìàññèâ áàéò - çàïðîñ ê ñåðâåðó*)
   len_query:DINT;                     (*êîëè÷åñòâî áàéò äëÿ ïåðåäà÷è - äëèíà çàïðîñà*)
   socket:DINT;                        (*äåñêðèïòîð ñîêåòà*)
END_VAR
VAR
   num:DINT   ;                        (*êîëè÷åñòâî ïåðåäàííûõ áàéò*)
   send_bytes:DINT   ;                  (*êîëè÷åñòâî îòïðàâëåííûõ áàéò*)
   wait_bytes:DINT;                     (*êîëè÷åñòâî îæèäàþùèõ áàéò*)
   fdWrite:SOCKET_FD_SET;
   tvTimeout:SOCKET_TIMEVAL;
END_VAR

tvTimeout.tv_sec := 0;
tvTimeout.tv_usec := 50000;
fdWrite.fd_count := 1;
fdWrite.fd_array[0] := socket;
SysSockSelect(SOCKET_FD_SETSIZE, 0, ADR(fdWrite), 0, ADR(tvTimeout)) ;
IF fdWrite.fd_array[0]=socket THEN
wait_bytes:=len_query;
send_bytes:=0;
(*öèêë îòïðàâêè äàííûõ íà ñåðâåð*)
WHILE send_bytes<wait_bytes DO
   num:=SysSockSend(socket,query_pointer+send_bytes*SIZEOF(query_pointer^),wait_bytes,0);
   IF num=-1 OR num=0 THEN
      send_bytes:=num;
      EXIT;
   END_IF
   send_bytes:=send_bytes+num;
   wait_bytes:=wait_bytes-num;
END_WHILE
TCP_SEND_INFO:=send_bytes;
ELSE TCP_SEND_INFO:=-1;
END_IF


а вот код сервера:
Код:
#include <WS2tcpip.h>
#include <iostream>
   using namespace std;

void main()
 {
   WORD wVersionRequested;
   WSADATA wsaData;
   wVersionRequested=MAKEWORD(2,2);
   WSAStartup(wVersionRequested,&wsaData);

   SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   if (s==-1)
   {
      cout<<"Creating socket...no"<<endl;
      system("pause");
   }
   else
   {
      cout<<"Creating socket...ok"<<endl;
      struct sockaddr_in sin;
      sin.sin_family = AF_INET;
      sin.sin_port = htons(3490);
      sin.sin_addr.s_addr = INADDR_ANY;
      memset(&(sin.sin_zero), '\0', 8);
      int err = bind( s, (struct sockaddr *)&sin, sizeof(sin));
      if (err==-1)
      {
         cout<<"Bind port 3490 on my local machine...no"<<endl;
         system("pause");
      }
      else
      {
         cout<<"Bind port 3490 on my local machine...ok"<<endl;
         err = listen( s, SOMAXCONN);
         if (err==-1)
         {
            cout<<"Listening port 3490 on my local machine...no"<<endl;
            system("pause");
         }
         else
         {
            cout<<"Listening port 3490 on my local machine...ok"<<endl;   
            while (true)
            {
               char buff[4]={1,2,3,4};
               sockaddr_in from;
               int fromlen=sizeof(from);
               cout<<"Wait connection..."<<endl;
               SOCKET  s1 = accept(s,(struct sockaddr*)&from, &fromlen);
               cout<<"Connection from DK55(CodeSys) sucsessfull!"<<endl;
               fromlen = send( s1, buff,4, 0 );
               cout<<"Sending to client "<<fromlen<<" bytes"<<endl;
               fromlen = recv( s1, buff,4, 0 );
               cout<<"Recving from client "<<fromlen<<" bytes"<<endl;
               closesocket(s1);
            }
             WSACleanup();
            system("pause");
         }
      }
   }
 }


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Пн июл 30, 2012 6:26 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
в результате кучи разных тестов было обнаружено следующее:
если сервер отправляет N байт, и в клиенте вызвать SysSockRecv(socket, answer_pointer, N, 0), то функция возвращает полученное количество байт, т. е. число N, если же вызвать SysSockRecv(socket, answer_pointer, 1000, 0), но передавать сервером другое количество байт, то зависает (ошибка #16: watchdog erxpired)


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Ср авг 01, 2012 11:00 am 
Не в сети

Зарегистрирован: Ср июн 20, 2007 12:10 pm
Сообщения: 31
Попробуйте после создания сокета перевести его в неблокирующий режим:
Код:
diParam:DINT:=1; (*параметр для SysSockSetOption и SysSockIoctl*)
di_IoctlRez:=SysSockIoctl(diSocket, SOCKET_FIONBIO, ADR(diParam));
Еще в своем проекте отключал режим буферизации: устанавливал параметр SOCKET_TCP_NODELAY с помощью функции SysSockSetOption.
PS. ПЛК другой, проверьте наличие этих функций у себя.


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Чт авг 02, 2012 10:53 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
Avgur писал(а):
Попробуйте после создания сокета перевести его в неблокирующий режим:
Код:
diParam:DINT:=1; (*параметр для SysSockSetOption и SysSockIoctl*)
di_IoctlRez:=SysSockIoctl(diSocket, SOCKET_FIONBIO, ADR(diParam));
Еще в своем проекте отключал режим буферизации: устанавливал параметр SOCKET_TCP_NODELAY с помощью функции SysSockSetOption.
PS. ПЛК другой, проверьте наличие этих функций у себя.

обе функции в моем ПЛК присутствуют, в результате получено: при установке сокета, как неблокирующего, connect не проходит, а
SysSockSetOption(mySocket, SOCKET_IPPROTO_TCP, SOCKET_TCP_NODELAY, ADR(MY_TRUE), SIZEOF(MY_TRUE))=FALSE, опция не установлена


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Чт авг 02, 2012 2:23 pm 
Не в сети

Зарегистрирован: Вт сен 15, 2009 7:48 am
Сообщения: 47
Добрый день,
Сегодня потестировали чип, слали на эхо-сервер в инете данные с чипа и принимали обратно.
Завтра наш сотрудник выложит не сложный текст тестовой программы. Правда, читаю Ваши новые посты, мы тоже принимали (ожидали) столько байт сколько слали, а не больше, и это работало без проблем в блокирующем режиме.

Александра попрошу проверить ресив с параметром данных большим чем нужно. Он расскажет о результатах.


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Чт авг 02, 2012 2:41 pm 
Не в сети

Зарегистрирован: Вт сен 15, 2009 7:48 am
Сообщения: 47
На счет НЕблокирующего режима, надо быть аккуратным, ибо вся синхронизация приема-записи становится чуть сложнее. В этом режиме ф-ции работы с сокетом перестают ожидать результата и отпускают процесс практически моментально. Нужно будет выставлять вручную паузы между созданием, открытием, записью, чтением и закрытием сокета.


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Чт авг 02, 2012 2:55 pm 
Не в сети

Зарегистрирован: Вт сен 15, 2009 7:48 am
Сообщения: 47
Почему вы используете в TCP_GET_INFO answer_pointer как DWORD а не как указатель на байт?


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Пт авг 03, 2012 5:53 am 
Не в сети

Зарегистрирован: Ср июл 11, 2012 6:22 pm
Сообщения: 23
Mikhail Shvetsov писал(а):
Почему вы используете в TCP_GET_INFO answer_pointer как DWORD а не как указатель на байт?

был и вариант с указателем на байт, я с codesys работаю всего месяц, поэтому по ходу работы эксперементирую,
хотя соглашусь что указатель на байт - более корректный вариант...

в том-то и дело, что пакет неизвестного размера может прийти и его надо будет обработать, соответственно ожидать пакет конкретного размера,заложенного в программе, будет неправильным...
Если судить по описанию функции SysSockRecv - она вызывает функцию Recv ОС, а в ней SysSockRecv(socket, answer_pointer, N, 0) параметр N - это размер буфера приема, т. е. грубо говоря - это максимальное число байт, которое может принять за 1 передачу наш Recv, возвращать же она должна реально полученное число байт(например получила пакет размером 7 байт при максимально возможных N=1000)

так же при тестах, если SysSockRecv(socket, answer_pointer, N,SOCKET_MSG_PEEK) весь буфер размером N заполняется поочередно пакетами из 7 байт и Recv возвращает как результат N полученных байт
Цитата:
Флаг MSG_PEEK ("просмотр сообщения") означает, что полученное сообщение не удаляется из буфера сокета и будет прочитано повторно последующими функциями чтения, например, функцией recv().

так же нашел на этом форуме выложенный пример TCP_UDP в соответствующем разделе, в нем аналогичная ситуация наблюдается


Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Пт авг 03, 2012 9:38 am 
Не в сети

Зарегистрирован: Чт авг 02, 2012 12:59 pm
Сообщения: 5
Вот код для теста. При выделении буфера в 1000 байт под ожидаемые данные, что больше, чем было отправлено (13 байт), SysSockRecv возвращает именно эти 13 байт.

Код:
PROGRAM PLC_PRG
VAR
   str1                 : STRING            := 'Hello World!';      (*Отправляемые данные*)
   str2                 : STRING;                                   (*Принимаемые данные*)
   stIPaddres           : STRING            := '92.241.103.178';    (*IP-дрес настроенного echo-сервера*)
   port                 : UINT              := 10005;               (*Порт настроенного echo-сервера*)
   hSocket              : UDINT;                                    (*Дескриптор сокета*)
   sa                   : SOCKADDRESS;                              (*Структура*)
   result               : BOOL;                                     (*Флаг соединения с сервером*)
   numberOfBytesSend    : DINT;                                     (*Число посланных байт*)
   numberOfBytesRecv    : DINT;                                     (*Число принятых байт*)
   counterOfCycle       : UDINT;                                    (*Счётчик циклов программы*)
END_VAR


Код:
sa.sin_family            := SOCKET_AF_INET;
sa.sin_port              := SysSockHtons(port);
sa.sin_addr              := SysSockInetAddr(stIPaddres);
hSocket                  := SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_TCP);   (*Открытие сокета*)
result                   := SysSockConnect(hSocket, ADR(sa), SIZEOF(sa));                       (*Соединение с сервером*)
numberOfBytesSend        := SysSockSend(hSocket, ADR(str1), LEN(str1) + 1 ,0);                  (*Отправка данных*)
numberOfBytesRecv        := SysSockRecv(hSocket, ADR(str2), 1000, 0);                           (*Приём данных*)
counterOfCycle           := counterOfCycle + 1;                                                 (*Увеличение счётчика на единицу*)
SysSockClose(hSocket);   


Последний раз редактировалось Aleksandr Baranov Пт авг 03, 2012 8:52 pm, всего редактировалось 4 раза.

Вернуться к началу
 Заголовок сообщения: Re: странная работа SysSockRecv
СообщениеДобавлено: Пт авг 03, 2012 10:53 am 
Не в сети

Зарегистрирован: Чт авг 02, 2012 12:59 pm
Сообщения: 5
flint21rus писал(а):
beck dk55

На базе какого чипа, SC23 или SC24? Какой номер версии рантайма? RTOS Full или Embedded?


Вернуться к началу
Показать сообщения за:  Поле сортировки  
Начать новую тему  Ответить на тему  [ 22 сообщения ]  На страницу 1 2 След.

Часовой пояс: UTC+01:00


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Limited
Русская поддержка phpBB