Reprint: http://www.cnblogs.com/xiangshancuizhu/archive/2012/10/05/2711882.html
Because the socket recv () method is blocking, when there are multiple clients connecting to the server, one of the socket's recv calls is blocked, leaving the other links unable to continue. If you want to change this has been waiting for the state of anxiety, can be multi-threaded to achieve (no longer waiting, at the same time to recv, while blocking), each socket connection using a thread, so inefficient, it is impossible to deal with the situation of large load (yes, occupy a variety of resources, computer Ah, you can not afford).
At this point we can take the Select model,Select allows the process to instruct the kernel to wait for any one of multiple events to occur, and wake it only after one or more events have occurred or a specified amount of time has passed. Select tells the kernel which descriptive words to be interested in and how long to wait. This is called a non-blocking model, where a process or thread executes this function without having to wait for the event to occur, once the execution is returned, and the return is worth different to the execution of the response function, if the event occurs in the same way as blocking, and if the event does not occur, return a code to tell the event not to occur. The process or thread continues to execute, so it is more efficient.
Function prototypes for select:
int
select
(
int
nfds,
//Winsock中此参数无意义
fd_set* readfds,
//进行可读检测的Socket
fd_set* writefds,
//进行可写检测的Socket
fd_set* exceptfds,
//进行异常检测的Socket
const struct
timeval* timeout
//非阻塞模式中设置最大等待时间
)
|
Parameter list:
int MAXFDP is an integer value that refers to the range of all file descriptors in the collection,that is, the maximum value of all file descriptors plus 1, can't be wrong!The value of this parameter in Windows does not matter, can be set incorrectly。
Fd_set *readfds is a pointer to the FD_SET structure, which should include the file descriptor, we want to monitor the read changes of these file descriptors, that is, we care about whether we can read the data from these files,If a file in this collection is readable, select returns a value greater than 0, which indicates that a file is readable, and if there is no readable file, the timeout parameter is used to determine whether to time out, and if timeout is exceeded, select returns 0, and a negative value is returned if an error occurs.you can pass in a null value, indicating that you do not care about any file read changes。
Fd_set *writefds is a pointer to the FD_SET structure, which should include the file descriptor, we want to monitor the write changes of these file descriptors, that is, we care about whether we can write data to these files,If a file in this collection is writable, select returns a value greater than 0, indicates that there is a file to write, if there is no writable file, then according to the timeout parameter to determine whether to timeout, if timeout time exceeded, select returns 0, if an error returns a negative value.you can pass in a null value to indicate that you do not care about any file write changes。
Fd_set *errorfds with the above two parameters to monitor file error exceptions.
The struct timeval* timeout is the time-out for Select, which is critical, which allows the select to be in three states:
First, if NULL is passed in as a parameter, that is, the time structure is not passed in, the select is put in a blocking state, it must wait until one of the file descriptors in the monitor file descriptor collection has changed;
Second, if the time value is set to 0 seconds and 0 milliseconds, it becomes a purely non-blocking function, regardless of whether the file descriptor changes, immediately return to continue execution, the file has no change return 0, there is a change to return a positive value;
Third, the value of timeout is greater than 0, which is the waiting time-out period, that is, select in timeout time block, the timeout period within the time of the arrival of the return, otherwise after the timeout anyway must return, the return value with the above.
return value: Negative: Select Error
Positive values: Some files are read-write or error-prone
0: Wait timeout, no writable or incorrect files
Parameter explanation:
Parameter 1 Nfds: This parameter is an ignored parameter, we pass in 0 in the program, the purpose is to be compatible with the Berkeley socket.
Parameter 2 Readfds: Readability monitoring collection, readability refers to the arrival of a connection, data arrival, connection closed, reset, or terminate.
Parameter 3 Writefds: Writable monitoring set, writable index can be sent, the connection can be successful.
Parameter 4 Exceptfds: Exception monitoring collection, exception refers to connection failure, incoming data arrival
Parameter 4 timeout: This parameter specifies the time the select will wait, the structure is simple, if you are interested to see the MSDN
Note: At least one of the three watch sets in the Select parameter cannot be empty, and any other two can be empty
fd_set structure , this structure is used to install sockets, to monitor the socket to the structure, and then with the SELECT function to monitor.
struct fd_set { u_int fd_count; // how many are SET? SOCKET fd_array[FD_SETSIZE]; // an array of SOCKETs } ; |
Four macros that are tightly coupled with the Select model:
FD_CLR (s,*set) removes the handle s from the queue set.
Fd_isset (S, *set) checks if the handle s exists with the queue set.
Fd_set (S,*set) adds the handle s to the queue SET.
Fd_zero (*set) initializes the set queue to an empty queue.
The Select selection mode relies on the Select function, and the idea is to have the Select function Monitor incoming fd_set (with your socket handle in fd_set) and clear the socket in Fd_set if nothing happens.
Such as:
timeval outTime;
outTime.tv = 1;
//设置等待时间为1s
outTime.usec = 0;
//毫秒
fd_set fdread;
while
(
true
)
{
FD_ZERO(&fdread);
FD_SET(sessionSock, &fdread)
//sessionSock为之前创建的会话套接字
if(
select(0, &fdread, NULL, NULL, &outTime) > 0) { if
(FD_ISSET(sessionSock, &fdread))
//判断套接字是否还在集合中
{
recv_cnt = recv(sessionSock, buf, bufSize, 0);
}
else
{
//没有数据写入,进行其他操作
} }
}
|
Socket Select () model