The select model of the Winsock IO model

Source: Internet
Author: User

It is called a select model because it uses the SELECT function primarily to manage I/O. This model was designed from a UNIX system to allow applications that want to avoid blocking on socket calls to have the ability to manage multiple sockets.

int Select (

int Nfds,//Ignore, only for compatibility with Berkeley sockets

fd_set* Readfds,//points to a socket collection to check its readability

fd_set* Writefds,//points to a socket collection to check for its writable properties

fd_set* Exceptfds,//point to a socket collection to check for errors

const struct TIMEVAL* Timeout//Specifies the maximum time this function waits, and if NULL, the maximum time is infinitely large

);

The Select model is the most common I/O model.

use int Select (int Nfds, fd_set far* Readfds, fd_set far* writefds,fd_set far* exceptfds,const struct timeval FAR * time Out);

function to check if the socket socket you want to invoke already has the data that needs to be processed.

The select contains three socket queues, representing: Readfds, checking readability, Writefds, checking for writable, Exceptfds, exception data. Timeout is the return time of the Select function.

For example, we want to check if a socket has data to be received, we can add the socket handle to the readability check queue, and then call Select, and if the socket has no data to receive, the SELECT function removes the socket from the readability check queue. So we just have to check if the socket handle is still in the readability queue, so we can see if there is any data to be received.

The timeout parameter controls when the select completes. If the timeout parameter is a null pointer, then select will block until a description word satisfies the condition, otherwise, timeout points to a timeval structure that specifies how long the select call waits before returning. If Timeval is {0,0}, then select returns immediately, which can be used to inquire about the state of the selected socket, and if it is in this state, the select call can be considered non-blocking and all assumptions applicable to non-blocking calls apply to it, for example, the blocking hook function should not be called. and the Windows nested interface implementation should not yield.

The function call succeeds, returning the sum of all the sockets for which the network event occurred. If the time limit is exceeded to return 0, failure returns SOCKET_ERROR.

typedef struct FD_SET {

U_int Fd_count; The size of the following array

SOCKET Fd_array[fd_setsize]; Array of socket handles

} fd_set;

    • Fd_zero (*set)                               Initialize set is an empty collection. The collection should always be emptied before use
    • fd_clr (S, *set)                            Remove socket S
    • from set Fd_isset (s, * Set)                          Check S is not a member of SET, if True
    • fd_set (S, *set)                              add socket to collection
typedef struct timeval{long tv_sec;                      Indicates how many seconds to wait long tv_usec; Indicates how many milliseconds to wait} timeval; Here is an example of using select Mode, which listens on port 4567 after running, accepts client connection requests, and prints the received data. (The original single thread can also manage multiple sockets)
//////////////////////////////////////////////////////////  //initsock.h File#include<winsock2.h>#pragmaComment (lib, "Ws2_32")//Link to Ws2_32.libclasscinitsock{ Public: Cinitsock (BYTE minorver=2, BYTE majorver =2)    {        //Initialize Ws2_32.dllWsadata Wsadata; WORD sockversion=Makeword (Minorver, majorver); if(:: WSAStartup (Sockversion, &wsadata)! =0) {exit (0); }    }    ~Cinitsock () {:: WSACleanup (); }};//////////////////////////////////////////////////////  //select.cpp File#include".. /common/initsock.h"#include<stdio.h>Cinitsock Thesock; //initializing the Winsock libraryintMain () {USHORT nport=4567;//port number that this server listens on//Create a listener section wordSOCKET Slisten =:: Socket (af_inet, sock_stream, ipproto_tcp);    Sockaddr_in sin; Sin.sin_family=af_inet; Sin.sin_port=htons (Nport); Sin.sin_addr. S_un. S_addr=Inaddr_any; //bind a socket to a local machine    if(:: Bind (Slisten, (sockaddr*) &sin,sizeof(sin)) ==socket_error) {printf ("Failed bind () \ n"); return-1; }    //Enter listening mode:: Listen (Slisten,5); //Select model processing Process//1) Initialize a set of Fdsocket, add a listener handle to this collectionFd_set Fdsocket;//all available nested word collectionsFd_zero (&fdsocket); Fd_set (Slisten,&fdsocket);  while(TRUE) {//2) Pass a copy of the Fdsocket collection fdread to the Select function,//When an event occurs, the Select function removes the handle of the socket with no pending I/O operations in the Fdread collection, and then returns. Fd_set Fdread =Fdsocket; intNret =::Select(0, &fdread, NULL, NULL, NULL); if(Nret >0)        {            //3) by comparing the original Fdsocket set with the Fdread set processed by SELECT,//determine which of the nested sections have pending I/O and further process these I/O.              for(inti =0; I < (int) Fdsocket.fd_count; i++)            {                if(Fd_isset (fdsocket.fd_array[i), &fdread)) {                    if(Fdsocket.fd_array[i] = = Slisten)//(1) Listen to the socket to receive a new connection                    {                        if(Fdsocket.fd_count <fd_setsize)                            {sockaddr_in addrremote; intNaddrlen =sizeof(Addrremote); SOCKET snew=:: Accept (Slisten, (sockaddr*) &addrremote, &Naddrlen); Fd_set (Snew,&fdsocket); printf ("connection received (%s) \ n",:: Inet_ntoa (ADDRREMOTE.SIN_ADDR)); }                        Else{printf ("Too much connections! \ n"); Continue; }                    }                    Else                    {                        Charsztext[ the]; intNRECV =:: Recv (Fdsocket.fd_array[i], Sztext, strlen (Sztext),0); if(Nrecv >0)//(2) readable{SZTEXT[NRECV]=' /'; printf ("data received:%s \ n", Sztext); }                        Else                                //(3) connection shutdown, restart, or interrupt{:: Closesocket (Fdsocket.fd_array[i]); FD_CLR (Fdsocket.fd_array[i],&fdsocket); }                    }                }            }        }        Else{printf ("Failed Select () \ n");  Break; }    }    return 0;}

General Process:  

Create a server socket
Socket
Bind to Address
Bind
Enter listening mode
Listen
Select mode
Constructing Fd_set Collections
Fd_set Fdsocket;
Emptying the Fd_set collection merges the server sockets into
Fd_zero (&fdsocket);
Fd_set (Slisten, &fdsocket);
Cycle
Duplicate a copy of the Fd_set set merge into Select to detect
Fd_set fdread = Fdsocket;
int nret =:: Select (0, &fdread, NULL, NULL, NULL);
Corresponding processing according to the select result (Accept Read)


Summary: Through the Select mode, the implementation of the listening socket of the accept and the client's read, as well as between the client read, can not always be blocked there, but at the time of the corresponding event and then the blocking process, Convert the Accept and read two long blocks to select a long block.
The advantage of using select is that the program can handle multiple socket connections at the same time in a single line range, which avoids the problem of thread bloat in blocking mode. However, the number of sockets added to the FD_SET structure is limited, by default, the maximum value is fd_setsize, which is defined as 64 in the Winsock2.h file. To increase the number of sockets, the application can define fd_setsize as a larger value (this definition must appear before the inclusion of Winsock2.h).    However, the custom value cannot exceed the limit of the Winsock downlevel provider (typically 1024). Also, if the value of fd_setsize is too large, server performance will be affected. For example, with 1000 sockets, you have to set these 1000 sockets before calling Select, and after select returns, you must check the 1000 sockets.

The select model of the Winsock IO model

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.