Understanding and Handling WINSOCK Error 10035
WINSOCK error 10035 ("Operation would block") occurs when a socket is temporarily unable to send or receive data because the system buffer is full. For most IPWorks users, with the exception of those using asynchronous components, it is generally not necessary to handle this error because the components manage it automatically.
In the IPWorks and IPWorks SSL toolkits, WINSOCK error 10035 means "Resource not available" or "Operation would block". This error happens when the WINSOCK buffer of either the client or server side become full.
Two situations in which a WINSOCK error 10035 might arise are as follows:
- Sending a large amount of data through the socket, causing the system's output buffer to become full.
- Sending data through the socket to the remote host, but the remote host's input buffer is full (because it is receiving data slower than is being sent).
Background of WINSOCK Error 10035
When data is sent, it is first passed to the TCP/IP subsystem of the machine (i.e., WINSOCK). The system buffers this data (in the OutBuffer) and begins sending it to the remote host as quickly as possible, which is limited by how fast the receiver can accept it. If the OutBuffer becomes full because data is being sent faster than the system can transmit it, you will receive WINSOCK error 10035.
Optionally Handling WOULDBLOCK
When using TCPClient or TCPServer, handle this condition by catching WINSOCK error 10035 and waiting for the component's ReadyToSend event to fire. This event indicates that the system is ready to send data again. At that time, the remaining data may be sent. However, it is generally not necessary to handle this error because the components manage it automatically.
The example below loops until all data has been sent. Under normal conditions, the loop executes only once. However, if the output buffer fills, the SendBytes call inside the loop fails with WINSOCK error 10035 (error code 135, "Operation would block"). The code then waits for the ReadyToSend event (using a boolean flag such as ready) and retries the send operation.
Please note that:
-
The ReadyToSend event fires only if none of the data was sent (i.e., when BytesSent equals 0). If some data was successfully sent, the code should immediately attempt to send the remaining data without waiting for the event.
-
BytesSent always returns 0 when the component is operating in synchronous mode (i.e., when the Timeout property is set to a positive value), so this approach applies only when Timeout is 0.
-
If using a .NET, Java, or related IPWorks or IPWorks SSL toolkit, then in addition to the information below, the Timeout property can be set to a positive value and simultaneous sends can be performed by utilizing a background thread for each send. This is only possible in .NET and Java because those toolkits are thread-safe.
// The ReadyToSend event sets the ready flag when the component can send data again.
bool ready = false;
tcpclient.OnReadyToSend += (s, e) => { ready = true; };
while (length > 0) { // There are still bytes to send.
try {
ready = false;
tcpclient.SendBytes(data, offset, length);
// All of the remaining data was sent.
length = 0;
} catch (nsoftware.IPWorks.IPWorksException ex) {
if (ex.Code != 135) throw; // 135 is the WOULDBLOCK error.
// If no data was sent, wait for the ReadyToSend event before retrying.
if (tcpclient.BytesSent == 0) {
while (!ready) tcpclient.DoEvents();
}
// Skip past any data that was sent, and retry with the rest.
offset += tcpclient.BytesSent;
length -= tcpclient.BytesSent;
}
}
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.