This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: FreeBSD problem with UDP sockets


Thanks Andrew, that did the trick. I'm still not sure it is "correct". But I'm not an expert at interpreting standards.

David Brennan

Andrew Lunn wrote:

On Wed, Aug 11, 2004 at 08:10:46PM -0700, David Brennan wrote:


I am currently having a problem with FreeBSD sockets.
Setup: i386-pc 82559, latest snapshot from snapshot service.

Background: Our application uses a UDP communication protocol over 2
sockets. Each one is a validated half duplex channel. That is the
sendSocket will receive acknowledgments of previous sends and recvSocket
will send acknowledgments of previous receives.
Implementation: I open two (UDP) sockets (sendSocket, and recvSocket).
I then do a select on either port. Once I receive a packet, I query each
socket to see if FD_ISSET. When I send a packet (from extenal host) to the second socket checked (recvSocket), the first socket returns with FD_ISSET, then my code goes into a blocking recvfrom and hangs since no data was actually on that socket..


Here are code snippets showing how the sockets are created, selected,
then received. This code has worked fine in pSOS and VxWorks, so I don't
think there is a fundamental problem here, unless there is some secret
to eCos implementation of BSD sockets.

Any help would be greatly appreciated.

David Brennan

// Two sockets are created (sendSocket, recvSocket):

  //  Create the socket
  socketM = socket(AF_INET, SOCK_DGRAM, 0);

  if (socketM < 0)
  {
      FATALSYS(("Cannot create socket"));
  }

sockAddrInT localAddr((inAddrT((ULong) INADDR_ANY)), localPortI);

  //  Bind the socket to local address and port number
  int err = bind(socketM, &localAddr, sizeof(sockaddr_in));
  if( err < 0 )
  {
      str32T addrS;
      FATALSYS(("Can't bind socket to local IP port %s:%d",
                localAddr.AddrStr(addrS.CharP()),
                localPortI
              ));
  }




So the above code creates socketM. Fine.


// Sockets are waited on for receive data (infinite wait):

fd_set readMask;

  FD_ZERO(&readMask);
  pAssert(InRange(sendSocket, 0, FD_SETSIZE-1));           // Limit to
keep FD_SET from writing out of readfds
  pAssert(InRange(recvSocket, 0, FD_SETSIZE-1));           // Limit to
keep FD_SET from writing out of readfds
  FD_SET(sendSocket, &readMask);
  FD_SET(recvSocket, &readMask);

// Use select to wait for input from either the send or receive
sockets
long err = select(FD_SETSIZE, &readMask, NULL, NULL, NULL);



Here you are using sendSocket and recvSocket which we have not seen created. If we get passed select we know that one of these two sockets has data on them.




  if( err < 0 )
  {
      FATALSYS(("select()=%d ", err));
      return( 0 );
  }

// Once select() returns successfully, check each socket (sendSocket,
recvSocket) for data:

  // Set of socket/file descriptors
  fd_set readfds;

  // Clear all socket selections from the read file descriptor set
  FD_ZERO(&readfds);

  // Select only this socket in the read file descriptor set
  // Limit to keep FD_SET from writing out of readfds
  pAssert(InOrderedRange(socketM, 0, FD_SETSIZE-1));
  FD_SET(socketM, &readfds);

  // Create a wait timeout
  timeval waitTime;
  waitTime.tv_sec = 0L;
  waitTime.tv_usec = 0;

// Use select on this socket to determine if there is pending read data
int result = select(FD_SETSIZE,
&readfds,
NULL,
NULL,
&waitTime
);



Now we are back to socketM.


What is not clear for me is the relationship between sendSocket,
recvSocket and socketM.




  if( result < 0 )
  {
      FATALSYS(("Error in: select(%d)", socketM));
  }

int isSet = FD_ISSET(socketM, &readfds);



Here is your problem. With passing {0,0} for waitTime, you are doing a poll. If there is nothing to receive on the socket, select will return 0, but it is not updating the readfds. Read the code in packages/io/fileio/current/src/select.cxx.

This might be an eCos bug. It might not be as well.  The Posix
standard at not 100% clear on this issue when i read
it. http://www.opengroup.org/onlinepubs/009695399/toc.htm

   On failure, the objects pointed to by the readfds, writefds, and
   errorfds arguments shall not be modified. If the timeout interval
   expires without the specified condition being true for any of the
   specified file descriptors, the objects pointed to by the readfds,
   writefds, and errorfds arguments shall have all bits set to 0.

When you have passed a timeout of {0,0} you are doing a poll. So the
timeout has not expired. However, we are not returning an error code
so it could also be said we are not in the failure case either.

To make your code work with eCos, check to see if the return value is


0.





  if( isSet != 0 )
  {
      respPktT respPkt;
      sockAddrInT sendersAddr;

recvfrom( socketM,
(char *) (&respPkt),
sizeof(respPkt),
0, // flags
(sockaddr *) (&sendersAddr),
(socklen_t) sizeof(sendersAddr)
)
}




Andrew




-- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]