blocking Mode
Windows Sockets perform I/O operations in both blocking and non-blocking modes. In blocking mode, the action function that executes until the I/O operation is complete waits without immediate return, and the thread where the function is located is blocked here. Instead, in nonblocking mode, the socket function returns immediately, regardless of whether or not the I/O is complete and the thread on which the function continues to run.
In blocking mode sockets, calling any of the Windows Sockets APIs will consume an indeterminate wait time. As shown in the figure, the process of waiting for data and replicating data in the kernel occurs when the recv () function is called.
When the recv () function is called, the system first checks to see if there is ready data. If the data is not ready, then the system is in a wait state. When the data is ready, the data is copied from the system buffer to the user space, and then the function returns. In a socket application, when the recv () function is called, the data is not necessarily present in the user space, then the recv () function is in a wait state.
The Windows Sockets program uses the "producer-consumer" mode to address these issues. In the program, the "producer" reads the data, and the "consumer" processes the read-in data according to the requirements. Typically "producer" and "consumer" exist in two threads, and when "producer" finishes reading the data, the thread synchronization mechanism is used, such as setting up an event notification "consumer" and "consumer" receiving the event to process the data being read.
When you use the socket () function and the WSASocket () function to create a socket, the default socket is blocked. This means that when the call to Windows Sockets API does not complete immediately, the thread waits until the operation is complete.
Not all Windows Sockets APIs will block if the socket is called as a parameter call. For example, when you call the bind (), listen () function in a socket with blocking mode, the function returns immediately. The Windows Sockets API calls that might block sockets are divided into the following four types:
1. Input action
Recv (), Recvfrom (), WSARecv (), and WSARecvFrom () functions. Call the function to receive data as a blocking socket for the parameter. If no data is readable in the socket buffer at this point, the calling thread sleeps until the data arrives.
2. Output operation
Send (), sendto (), WSASend (), and WSASendTo () functions. Calls the function to send data with a blocking socket as a parameter. If the socket buffer does not have free space, the thread will sleep until there is space.
3. Accept Connection
The Accept () and wsaacept () functions. Call the function as a blocking socket, waiting for the connection request to be accepted. If there is no connection request at this time, the thread goes to sleep.
4. Outgoing connections
The Connect () and WSAConnect () functions. For a TCP connection, the client invokes the function to initiate a connection to the server, with the blocking socket as the parameter. The function does not return until it receives a reply from the server. This means that TCP connections always wait at least one round trip to the server.
Using the blocking mode socket, the development of the network program is relatively simple and easy to implement. When you want to be able to send and receive data immediately, and the number of sockets processed is relatively small, it is appropriate to use blocking mode to develop a network program.
The inadequacy of blocking mode sockets is that it is difficult to communicate between a large number of well-established socket threads. When developing a network program using the producer-consumer model, each socket is assigned a separate read thread, a processing data thread, and an event for synchronization, which undoubtedly increases the overhead of the system. The biggest drawback is that when you want to handle a large number of sockets at the same time, it will not work, its extensibility is poor.
non-blocking mode
Set the socket to non-blocking mode, that is, notify the system kernel: when calling the Windows Sockets API, do not let the thread sleep, but should let the function return immediately. On return, the function returns an error code. As shown in the figure, a non-blocking pattern socket calls the recv () function multiple times. The kernel data is not ready when you call the recv () function the first three times. Therefore, the function immediately returns the WSAEWOULDBLOCK error code. The fourth time the recv () function is called, the data is ready to be copied into the application's buffer, and the recv () function returns a successful indication that the application is starting to process the data.
When you create a socket using the socket () function and the WSASocket () function, the default is blocked. After the socket is created, the socket is set to non-blocking mode by calling the Ioctlsocket () function. The functions under Linux are: Fcntl ().
When the socket is set to non-blocking mode, the calling function returns immediately when calling the Windows Sockets API function. In most cases, these function calls will call "failed" and return the Wsaewouldblock error code. Indicates that the requested operation did not have time to complete during the call. Typically, the application needs to call the function repeatedly until a successful return code is obtained.
It is necessary to note that not all Windows Sockets APIs are called in nonblocking mode and will return a wsaewouldblock error. For example, when you call the bind () function in a non-blocking socket for a parameter, the error code is not returned. Of course, the error code is not returned when the WSAStartup () function is called, because the function is the first call of the application and certainly does not return such an error code.
To set the socket to non-blocking mode, you can use the WSAAsyncSelect () and WSAEventSelect () functions in addition to the ioctlsocket () function. When the function is called, the socket is automatically set to non-blocking mode.
Because a non-blocking socket is used when calling a function, wsaewouldblock errors are often returned. So at any time, be careful to check the return code and prepare for the "failure". The application calls this function continuously until it returns to the successful instruction. In the above program manifest, the recv () function is constantly called in the while loop to read in 1024-byte data. This approach is a waste of system resources.
To do this, someone calls the recv () function using the MSG_PEEK flag to see if there is data readable in the buffer. Similarly, this method is not good. Because this practice is costly to the system, the application must call the recv () function at least two times to actually read the data. It is a good practice to use the "I/O model" of sockets to determine whether non-blocking sockets are readable and writable.
Non-blocking mode sockets are not easy to use compared to blocking mode sockets. With non-blocking mode sockets, you need to write more code to process the received Wsaewouldblock errors in each Windows Sockets API function call. Therefore, non-blocking sockets appear to be difficult to use.
However, the non-blocking sockets in the control of the establishment of multiple connections, the data received and received the amount of uneven, time is uncertain, obviously has the advantage. This kind of socket is difficult to use, but as long as the difficulty is eliminated, it is very powerful in function. In general, consider using the "I/O model" of sockets, which helps the application to manage the communication of one or more sockets asynchronously.