LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Why does WSARecvFrom retrun NULL for numberOfBytesTransferred

There are two functions in the WinSock SDK, recvfrom and WSARecvFrom.  I have used both with UDP/IP but WSARecvFrom returns NULL for the number of bytes received.  There is a line in WinSock Help that says it will return the number of bytes if it returns immediately.  I have used WSARecvFrom in a thread callback function and in a function that is called by a command button without the desired results.  With the command button I can break on the next line and find that the debugger indicates that the return is NULL for the number of bytes.  Can you point me to a way to make this feature work? Thanks
0 Kudos
Message 1 of 12
(6,054 Views)

The lpNumberOfBytesRecvd parameter in WSARecvFrom will be updated only if WSARecvFrom() completes successfully.  You can check the return value from WSARecvFrom() and call WSAGetLastError() if it is not 0.

You may not have a long enough timeout value set or you may be using WSARecvFrom() with an overlapped parameter.  If you are using overlapped i/o the call can terminate and will return SOCKET_ERROR.  You will probably get WSA_IO_PENDING from WSAGetLastError(), which means that the call has not completed.  When an outstanding overlapped operation is eventually completed, you can get the number of bytes transferred with a call to WSAGetOverlappedResult.  MSDN has more documentation. 

If you post  the relavant snippits of your code here, we can try and help you get it working.


 

0 Kudos
Message 2 of 12
(6,041 Views)

The WSA functions are an asynchronous, non-blocking extention of the Berkeley sockets model that has been around in the Unix world for a long time. The old blocking Berkeley-style functions are still there if you want to use them and a lot of code intended for Unix style systems may work on a Windows platform with relatively few (if any) changes at the socket level.

Using the WSA style functions is a bit trickier as mvr points out. If you use them in non-overlapped mode, they will block and pretty much act almost the same way as the old-style functions. Using them in overlapped mode is where things get a bit harder. Unfortunately, the use of these functions is a lot more than I can go into right now. Fortunately, there is this reference on MSDN:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/windows_sockets_sta...

 

You will definitely want to read pretty much the whole overview section with the exception of the IPv6 and NLA stuff (unless you are using those).

I know this is really a just a matter of semantics but the function is returning a count of zero bytes, not NULL. While NULL is defined as zero, they are not semantically the same thing. A NULL is generally an invalid pointer While a zero is simply zero.

Anyway, that's just a bit of nit-picking but it is a useful convention.

 

 

 

Martin Fredrickson
Test Engineer

Northrop Grumman
Advanced Systems and Products
San Diego, CA 92128
0 Kudos
Message 3 of 12
(6,035 Views)
Martin is correct.  The WSA form of sockets add features and capability but at the cost of complexity.  If you just want to establish basic UDP communication the older functions are much easier to implement and more portable.  If you need help with those, please post any questions you have again.
0 Kudos
Message 4 of 12
(6,022 Views)
Thanks for the advice.  WSARecvFrom returns value 997.  The message that is 16301 bytes long is displayed but the message length is 0.
setsocketopt sets a timeout of 1000ms.
WSASocket uses 0 in the last place so that overlapped is not set by default.
WSARecvFrom is called from a separate thread.
My LabwindowsCVI separate thread functionfollows.
 
//------------------------------------------------------------------------
int CVICALLBACK etherDataPortRecv (void *functionData)
{
long lngTemp;
char strTemp[100];
 DataBuf.len = BufLen;
 DataBuf.buf = RecvBuf;
 
 while(intQuiting == 0)
 {
  // Recieve the data on the port.
  if((intRetVal = WSARecvFrom(RecvSocket, &DataBuf, 1, lpdwDataBytesRecvd, &Flags, (SOCKADDR *) &SenderAddr,
        &SenderAddrSize, &Overlapped, NULL)) != 0)
  {
   intRetVal = WSAGetLastError();
   Fmt(strTemp, "%s<%i", intRetVal);
   MessagePopup("WSARecvFrom Error", strTemp);
  }
  lngTemp = (long)lpdwDataBytesRecvd;
  SetCtrlVal(hpnlWSAEthernetHost ,pnlWSAHost_strHostDataIn, RecvBuf);
  SetCtrlVal(hpnlWSAEthernetHost ,pnlWSAHost_nuBytesDataRecv, lngTemp);
 }
 return 0;
}
//------------------------------------------------------------------------
0 Kudos
Message 5 of 12
(6,008 Views)

I assume lpdwDataBytesRecvd is a DWORD.

might want to set lpdwDataBytesRecvd =0, Flags=0, if they are not already initialized.

You need a pointer to lpdwDataBytesRecvd, was that a typo?
WSARecvFrom(RecvSocket, &DataBuf, 1, &lpdwDataBytesRecvd, &Flags, (SOCKADDR *) &SenderAddr,
        &SenderAddrSize, &Overlapped, NULL)) ;

997 is IO_PENDING.  If you are not overlapped you might want to see if your data buffer could be invalid or too small.

Message Edited by mvr on 06-28-2006 03:52 PM

0 Kudos
Message 6 of 12
(6,003 Views)
Just wanted to make sure you knew about this, but there is an example of using UDP from CVI available here.

I hope this helps.
Bilal Durrani
NI
0 Kudos
Message 7 of 12
(5,987 Views)

Thanks for the attention, archieb

I find that the prototype from msdn.microsoft.com for WSARecvFrom is different than that in the NI WindowsSockets:PlatformSDK help file, so I switched to the NI version.

Now I am having troubles with LPWSABUF DataBuf

after delcaring

char FAR RecvBuf[1024];
u_long BufLen = 1024;

the compiler complains at the lines,

 DataBuf.len = BufLen;
 DataBuf.buf = RecvBuf;
 

that the Left operand of . has incompatible type LPWSABUF

Now what?

0 Kudos
Message 8 of 12
(5,964 Views)

I would have thought that DataBuf would have been of type WSABUF.  The LPWSABUF type is a pointer to a WSABUF structure.  How is DataBuf declared?

0 Kudos
Message 9 of 12
(5,954 Views)
The last message about pointers helped. Now declarations are:
WSADATA wsaData;
WSABUF DataBuf;
SOCKET RecvSocket;
struct sockaddr FAR SenderAddr;
WSAOVERLAPPED wsaOverlapped;
DWORD dwBytesDataRecv = 0, dwBytesControlRecv = 0, dwFlags = 0, dwBytesTransferred = 0;
 
and the function is called as:
  if((intRetVal = WSARecvFrom(RecvSocket, &DataBuf, 1, &dwBytesTransferred, &dwFlags, &SenderAddr,
        &intSenderAddrSize, &wsaOverlapped, NULL)) != 0)

This returns 0 and dwBytesTransferred has a good value in it.
 
My next problem is that if I make the message longer than 1000 Bytes the function returns -1 and LastError is 997
 
Now to find how to increase the maximum message size to 16kB or bigger
Thanks to all.
archieb 
0 Kudos
Message 10 of 12
(5,915 Views)