Question:
We are writing some sort of RCONSOLE utility for Win32. So we connect to RSPX in unsigned mode (one of the parameters of RSPX is signatures off). If we are not doing any recv on the client, the closesocket goes well, but if call recv, the NetWare server boots when closing the connection. May be this is both a problem of the Microsoft IPX/SPX implementation and of some NetWare modules.
The strangest thing we encountered is that when the first data packet arrives from NetWare (its size is 520), the ioctlsocket function tells us that we received 520 bytes but if we call recv trying to read 520 bytes, the recv function blocks. If we call recv trying to read n bytes where 0 abnormal because as the documentation states, recv must return the number of bytes received (a positive value), 0 if the connection is closed or SOCKET_ERROR when an error occured.
All these (the strange values returned by recv) happens when we are using a SOCK_SEQPACKET socket. The boot happens in both cases (i.e. when using SOCK_SEQPACKET or SOCK_STREAM).
Using a network monitor, we observed that the end of connection is negotiated correctly, because we receive the end of connection acknowledgement from the NetWare server.
Note that we wrote a year ago an MSDOS version of this utility, that runs well. Now we can not escape from this error in Windows.
Despite the WinSock documentation (the SO_LINGER option for setsockopt), abort the connection (without negotiating the end of connection).
Answer:
As for the WinSock behavior you describe, this is (almost) normal, although it does suggest a boundary condition problem in the Microsoft WinSock service provider. When operating in SEQPACKET mode, the WinSock API maintains messages boundaries, which basically says that one send() will be received in exactly one recv(). This functionality can be modified with the MSG_PARTIAL bit that lets you bundle multiple sends into a single message, and hence into a single receive. If you look at the WinSock 2 spec, you will see that WSARecv() defines 'flags' as an IN/OUT parameter. This allows WSARecv() to return the MSG_PARTIAL bit, which in turn lets you receive a part of a message before the whole thing has arrived.
WinSock 1.1 does not let you return flags on the recv() call, so a different convention was needed. The agreed upon convention is that recv() will flag a partial message receive by returning the recv() data count as a negative number. If you get 520, that tells you that you have received one full message of 520 bytes. If you get -520, that tells you that you have received a 520 byte fragment of a larger message.
In your case, an SPX packet that does not have the end-of-message bit set is received. The end-of-message bit is what SPX uses to differentiate messages. The Ioctl correctly reports that 520 bytes are available. The rule for recv() in SEQPACKET mode is that if (1) you set the MSG_PARTIAL bit in the flags field, or (2) you send down a buffer that is smaller than the full message, then the stack will generate a partial-message response. So, when you recv 0 < n < 520, the stack correctly returns a count of -n, telling you that you have not received the entire message. This should also have worked when you passed down 520 bytes, and the failure you mentioned would be considered a bug.
| iws2e010.exe | 28.0 K | 2005-04-06 |
--devsup
© 2008 Novell, Inc. All Rights Reserved.