The sendto function does not work during UDP communication.

Discussion and questions about programming with Ultibo.
johan
Posts: 2
Joined: Thu Sep 13, 2018 2:37 am

The sendto function does not work during UDP communication.

Postby johan » Fri Jan 04, 2019 8:51 am

Hello, I am Johan.
I use cpu as CM3L.
I am trying to make UDP communication. (SNTP Client function implementation)
However, the Sendto function does not continue to send data.

Code: Select all

unit CSntpClientManager;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils,Winsock2;

procedure CSntpClient.SNTPTest1();
var
  sntpRequest : TSNTPData;
  sntpReply   : TSNTPData;
  sntpRequestLen : integer;
  dstAddr     : TSockAddr;
  servAddr    : TSockAddr;
  servAddrLen : integer;
  targetAddr  : in_addr;
  optval      : integer;
  request_ts  : TSntpTime;
  ret         : integer;
  tv          : TimeVal;
  fds         : Tfdset;
  fd          : integer;
  secs        : LongWord;
  frac        : LongWord;
  t1, t2, t3, t4 : TDateTime;
  nb          : dword;
begin

  sntpRequest := Default(TSNTPData);
  sntpReply   := Default(TSNTPData);

  targetAddr.S_addr  := inet_addr(PChar(m_ipAddress));   //IP : 192.168.91.13

  LogMsg(' SNTP m_ipAddress : ' + m_ipAddress);
  LogMsg(' SNTP m_udpPort : ' + inttostr(m_udpPort));      //port : 123

  dstAddr     := Default(sockaddr_in);

  dstAddr.sin_addr.S_addr := targetAddr.S_addr;   //IP : 192.168.91.13
  dstAddr.sin_family      := AF_INET;
  dstAddr.sin_port        := htons(m_udpPort);         //port : 123

  try

    sntpSocket := Socket(AF_INET, SOCK_DGRAM, 0);

    if sntpSocket = -1 then begin
      LogMsg('SNTP Socket Error ''');
      exit(-1);
    end;

  except
    on E:Exception do
    begin
      LogMsg('SNTPClient Socket error: ' + E.ClassName + ': ' + E.Message);
      exit(-1);
    end;
  end;

  try
    optval := 1;
    ret := setsockopt(sntpSocket, SOL_SOCKET, SO_BROADCAST, PChar(@optval), sizeof(optval));
    nb := 1;
    //ret := ioctlsocket( sntpSocket , FIONBIO , @nb );
  except
    on E:Exception do
    begin
      LogMsg('SNTPClient setsockopt error: ' + E.ClassName + ': ' + E.Message);
      exit(-1);
    end;
  end;

  request_ts  := Default(TSntpTime);
  t1 := GetUTTime;

  EncodeTs(t1, request_ts);

  // 요청 패킷 생성

  sntpRequest.mode                   := $1B;
  sntpRequest.stratum                := 0;
  sntpRequest.poll                   := 6;
  sntpRequest.precision              := -10;
  sntpRequest.root_delay             := 0;
  sntpRequest.root_dispersion        := 0;
  sntpRequest.reference_identifier   := 0;
  sntpRequest.transmit_timestamp.secs     := SwapEndian(request_ts.secs);
  sntpRequest.transmit_timestamp.frac     := SwapEndian(request_ts.frac);

  servAddr    := Default(sockaddr_in);
  servAddrLen := sizeof (servAddr);

  LogMsg('sendto -----> ');

  try
    //ret := sendto(sntpSocket, sntpRequest, sizeof(sntpRequest), 0, dstAddr, sizeof(dstAddr));
    ret := sendto(sntpSocket, @sntpRequest, sizeof(sntpRequest), 0, @dstAddr, sizeof(dstAddr));
  except
    on E:Exception do
    begin
      LogMsg('SNTPClient sendto error: ' + E.ClassName + ': ' + E.Message);
      exit(-1);
    end;
  end;


  if ret = -1 then begin
    LogMsg('SNTP Sendto Error!!!');
    closesocket(sntpSocket);
    exit(-1);
  end;

  fd := sntpSocket;

  fds := Default(Tfdset);
  fd_zero(fds);
  fd_set(fd, fds);
  tv := Default(TimeVal);
  tv.tv_sec:=m_waitTimeout*1000;
  tv.tv_usec:=0;

  // 데이터가 들어올때까지 대기한다.
  LogMsg('select -----> ');

  try

    ret := select(fd+1, @fds, nil, nil, @tv);

  except
    on E:Exception do
    begin
      LogMsg('SNTPClient select error: ' + E.ClassName + ': ' + E.Message);
      exit(-1);
    end;
  end;



  if ret = -1 then begin
    LogMsg('SNTP Select Error!!!   timeout : ' + inttostr(m_waitTimeout) + 'sec');
    closesocket(sntpSocket);
    sntpSocket := 0;
    exit(-1);
  end else if ret = 0 then begin
    LogMsg('SNTP Select Timeout!!!   timeout : ' + inttostr(m_waitTimeout) + 'sec');
    closesocket(sntpSocket);
    sntpSocket := 0;
    exit(-1);
  end;

  // 들어온 데이터를 받고
  LogMsg('recvfrom -----> ');

  try

    //ret := recvfrom(sntpSocket, sntpReply, sizeof(sntpReply), 0, servAddr, servAddrLen);
    ret := recvfrom(sntpSocket, @sntpReply, sizeof(sntpReply), 0, @servAddr, @servAddrLen);

  except
    on E:Exception do
    begin
      LogMsg('SNTPClient recvfrom error: ' + E.ClassName + ': ' + E.Message);
      exit(-1);
    end;
  end;


  if ret = -1 then begin
    LogMsg('SNTP recv Error!!! ');
    closesocket(sntpSocket);
    sntpSocket := 0;
    exit(-1);
  end else if ret = 0 then begin
    LogMsg('SNTP recv ');
    closesocket(sntpSocket);
    sntpSocket := 0;
    exit(-1);
  end;

  closesocket(sntpSocket);
  sntpSocket := 0;

  secs := SwapEndian(sntpReply.transmit_timestamp.secs);
  frac := SwapEndian(sntpReply.transmit_timestamp.frac);

  LogMsg('============================================');
  LogMsg('============================================');
  printTime(sntpReply);

  if secs = 0 then begin
    LogMsg('SNTP Transmit_timestamp, time is zero, do not sync');
    exit(-1);
  end;

end;


If you execute it, it will be stopped until it is executed before the sendto function.
continue 'sendto ----->' and timeout
I do not know why the sendto function does not work.
User avatar
Ultibo
Site Admin
Posts: 2185
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: The sendto function does not work during UDP communication.

Postby Ultibo » Fri Jan 04, 2019 10:15 am

johan wrote:Hello, I am Johan.

Hello Johan, welcome to Ultibo.

johan wrote:I use cpu as CM3L.
I am trying to make UDP communication. (SNTP Client function implementation)
However, the Sendto function does not continue to send data.
...
I do not know why the sendto function does not work.

Let us test your code and see if we can figure why it doesn't work as you expect.

We'll post back here with more info as soon as we have a chance to test.
Ultibo.org | Make something amazing
https://ultibo.org
User avatar
Ultibo
Site Admin
Posts: 2185
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: The sendto function does not work during UDP communication.

Postby Ultibo » Mon Jan 07, 2019 11:34 pm

Hello Johan,

I tested your code and it seems to work for me, UDP packet is sent using sendto and a valid reply is received using recvfrom.

Your example wasn't complete so I had to fill in some missing details like the TSNTPData structure and a number of variables.

There were two things I noticed, first one is you must wait for an IP address to be assigned otherwise sendto will fail, you can find an example of how to wait for an IP address to be available in the WebServer example.

The other item I found was your select timeout is incorrect, in your code you do this:

Code: Select all

tv.tv_sec:=m_waitTimeout*1000;

but tv.tv_sec is seconds not milliseconds so that will cause a very long timeout.

Changing it to this fixes the problem:

Code: Select all

tv.tv_sec:=m_waitTimeout;

Hope that helps, please let us know how you go.
Ultibo.org | Make something amazing
https://ultibo.org

Return to “General”

Who is online

Users browsing this forum: No registered users and 2 guests