One of the Windows I/O models: Select model

Source: Internet
Author: User

1. Conceptual understanding

In network programming, we often see Synchronization (sync)/async (Async), blocking (block)/non-blocking (Unblock)

Four modes of invocation:

synchronization: The so-called synchronization is that when a function call is made, the call does not return until the result is obtained. It must be one.

One thing to do, wait for the previous piece to finish before you can do another.

For example, in a process in the C/S mode, your server submits a request to the client when the server has finished processing to return the result.

Can't do it.

Async: Asynchronous concept and synchronization relative. When an asynchronous procedure call is made, the caller does not get the result immediately. The caller is emitting a

After the call can continue to do their own thing, the caller through the state, notification to notify the caller, or through the callback function to handle the call.

blocking: A blocking call means that the current thread is suspended (the current thread is in a non-executable state, in this state, before the call result is returned).

The CPU does not assign a time slice to the thread, that is, the thread pauses to run, and the function returns only if the result is obtained.

non-blocking: The concept of non-blocking and blocking is relative, meaning that the function does not block the current process and returns immediately before it can be borrowed immediately.

difference: Someone will equate synchronous and blocking calls, in fact they are different, for synchronous calls, many times the current call

is still active, but logically the current function does not return. The current thread is suspended if it is blocked.

2.Select model principle and use steps

The Select (selection) model is the most common I/O model in Winsock. It is called the "select Model" because of its "central idea"

is to use the Select function to achieve the management of I/O! With the Select function, we determine if there is data on the socket, or can

Sockets to write data to a socket. The only reason to design this function is to prevent the application from being in lock mode when the socket is

An I/O binding call (such as send or recv) is forced into a "locked" state while preventing the socket from being in non-locked mode.

Generates a wsaewouldblock error. The Select function locks in the I/O operation, unless the conditions specified in the prior parameters are met.

The function prototypes for select are as follows:

int select (  int Nfds,                             fd_set FAR * Readfds,                 fd_set FAR * Writefds,                fd_set FAR * Exceptfds,               const STRU CT timeval FAR * timeout  );

Where the first parameter, Nfds, is ignored. The reason is still to provide this parameter, just to keep up with the early Berkeley socket application process

Compatible with the sequence. You can notice three fd_set parameters: one for readability (READFDS), one for check writable (WRITEFDS),

The other is for exception data (EXCEPFDS). Fundamentally, the Fdset data type represents a collection of a specific set of sockets. which

The Readfds collection includes sockets that meet any one of the following conditions:

There is data to read in.
The connection has been closed, re-erected, or aborted.
If listen has been called and a connection is being established, the Accept function call succeeds.
The Writefds collection includes sockets that meet any one of the following conditions:
There is data to be sent.
If the processing of a non-locking connection call has been completed, the connection succeeds.
Finally, the Exceptfds collection includes sockets that meet any one of the following conditions:
If the processing of a non-locking connection call has been completed, the connection attempt fails.
There is out-of-band (OUT-OF-BAND,OOB) data available for reading.

For example, suppose we want to test whether a socket is "readable", you must add your own socket to the Readfds collection, and then wait for the Select function

Complete. After the select is complete, you must determine whether your socket is still part of the Readfds collection. If the answer is yes, it indicates that the set

The word "readable" allows you to start reading data from it immediately. In three parameters (Readfds, WRITEDFSS, and Exceptfds), any two

Can be a null value (NULL), but at least one cannot be null! In any non-empty collection, at least one socket handle must be included;

Otherwise, the Select function does not have anything to wait for. The last parameter, timeout, corresponds to a pointer, which points to a timeval structure,

Used to determine how long the select waits for the I/O operation to complete. If timeout is a null pointer, then the select call "locks" indefinitely

Or pauses until at least one descriptor meets the specified condition after the end. The definition of the TIMEVAL structure is as follows:

struct Timeval {
Long tv_sec;
Long tv_usec;

} ;

Setting the timeout value to (0,0) indicates that select returns immediately, allowing the application to "poll" the select operation. For performance reasons

Consideration, such a setting should be avoided. When select completes successfully, all sockets that have just outstanding I/O operations are returned in the FD_SET structure

The total number of handles. If it exceeds the time set by Timeval, it will return 0. Whatever the reason, if the select call fails, it will return socket_error.

Before you monitor a socket with select, in your own application, you must assign the socket handle to a collection, set one or all

Read, write, and exception fd_set structures. After you assign a socket to any one collection, and then call Select, you know that a socket is

No such I/O activity is occurring. Winsock provides the following macro actions that can be used to process and inspect fd_set for I/O activities:

FD_CLR (S, *set): Removes the socket s from the S e T.
Fd_isset (S, *set): Check if S is a member of the set of S e t; if the answer is yes, then return T R U E.
Fd_set (S, *set): Adds the socket s to the set S e T.
F D _ Z E R O (* s e t): Initializes the S e t into an empty set.

For example, suppose we want to know if the data can be read securely from a socket without being stuck in an endless "lock" state, you can use

FD_SET the macro, assigns its own socket to the Fd_set collection, and then calls Select. To detect if your socket is still a Fd_read collection

, you can use the Fd_isset macro. Use the following procedure to complete the entire process of using Select to manipulate one or more socket handles:

1) Use Fd_zero macros to initialize each of the fd_set you are interested in.
2) Use the Fd_set macro to assign the socket handle to each fd_set that you are interested in.
3) Call the Select function and wait for the I/O activity to set one or more socket handles in the specified Fd_set collection.
When select finishes, the total number of socket handles set in all Fd_set collections is returned, and each collection is updated accordingly.
4) based on the return value of SELECT, our application can determine which sockets are not yet complete (pending)
I/O operations-the specific method is to check each Fd_set collection using the Fd_isset macro.
5) After knowing the "pending" I/O operation in each set, I process the I/O and then return to step 1) and continue in
Yes

When select returns, it modifies each fd_set structure to remove socket handles that do not exist for pending I/O operations. That's what we're doing in the above steps

(4), why use the Fd_isset macro to determine whether a particular socket is still in the collection.

3. Reference Code

Select.cpp: Defines the entry point of the console application.
//

#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>
using namespace Std;

#include <stdio.h>

#pragma comment (lib, "Ws2_32.lib")

#define PORT 8000
#define MSGSIZE 255
#define SRV_IP "127.0.0.1"

int g_nsockconn = number of 0;//request connections

Fd_setsize is defined in the Winsocket2.h header file, where Windows defaults to a maximum of 64
Use a macro definition to modify this value before including the Winsocket2.h header file


struct CLIENTINFO
{
SOCKET sockclient;
Sockaddr_in addrclient;
};

Clientinfo G_client[fd_setsize];

DWORD WINAPI workthread (LPVOID lpparameter);

int _tmain (int argc, _tchar* argv[])
{//Basic steps are not explained, network programming basics that blog is very detailed.
Wsadata Wsadata;
WSAStartup (Makeword (2,2), &wsadata);

Socket Socklisten = socket (AF_INET,SOCK_STREAM,IPPROTO_TCP);

Sockaddr_in addrsrv;
Addrsrv.sin_addr. S_un. S_ADDR = inet_addr (SRV_IP);
addrsrv.sin_family = af_inet;
Addrsrv.sin_port = htons (port);

Bind (Socklisten, (sockaddr*) &addrsrv,sizeof (sockaddr));

Listen (socklisten,64);

DWORD dwthreadidrecv = 0;
DWORD dwthreadidwrite = 0;

HANDLE hand = CreateThread (null,0, WORKTHREAD,NULL,0,&DWTHREADIDRECV);//processes used to handle the manipulation of messages
if (hand = = NULL)
{
cout<< "Create work thread failed\n";
GetChar ();
return-1;
}

SOCKET sockclient;
Sockaddr_in addrclient;
int nlenaddrclient = sizeof (SOCKADDR);//This place uses 0 to find a half day to find the wrong

while (true)
{
Sockclient = Accept (Socklisten, (sockaddr*) &addrclient,&nlenaddrclient);//The third parameter must be initialized according to the addrclient size.
Address information for the output connector
Cout<<inet_ntoa (ADDRCLIENT.SIN_ADDR) << ":" <<ntohs (Addrclient.sin_port) << "has connect!" <<endl;

if (sockclient! = invalid_socket)
{
G_client[g_nsockconn].addrclient = addrclient;//Save Connection Address information
G_client[g_nsockconn].sockclient = sockclient;//Join the connector queue
g_nsockconn++;
}


}

Closesocket (Socklisten);
WSACleanup ();

return 0;
}

DWORD WINAPI workthread (LPVOID lpparameter)
{
Fd_set Fdread;
int nret = 0;//record number of bytes sent or accepted
Timeval tv;//Setting Timeout wait time
Tv.tv_sec = 1;
tv.tv_usec = 0;
Char buf[msgsize] = "";

while (true)
{
Fd_zero (&fdread);
for (int i = 0;i < g_nsockconn;i++)
{
Fd_set (G_client[i].sockclient,&fdread);
}

Only the Read event is processed, but there is still a read and write message sent
nret = select (0,&FDREAD,NULL,NULL,&TV);

if (nret = = 0)
{//no connection or no read event
Continue
}

for (int i = 0;i < g_nsockconn;i++)
{
if (Fd_isset (G_client[i].sockclient,&fdread))
{
Nret = recv (g_client[i].sockclient,buf,sizeof (BUF), 0);

if (nret = = 0 | | (nret = = Socket_error && wsagetlasterror () = = Wsaeconnreset))
{
cout<< "Client" <<inet_ntoa (g_client[i].addrclient.sin_addr) << "closed" <<endl;
Closesocket (g_client[i].sockclient);

if (I < g_nsockconn-1)
{
Reject the failed sockclient, using the last of the array to fill up
G_client[i--].sockclient = g_client[--g_nsockconn].sockclient;
}
}
Else
{
Cout<<inet_ntoa (G_CLIENT[I].ADDRCLIENT.SIN_ADDR) << ":" <<endl;
cout<<buf<<endl;
cout<< "Server:" <<endl;
Gets (BUF);
strcpy (buf, "hello!");
nret = Send (G_client[i].sockclient,buf,strlen (BUF) +1,0);
}
}
}
}
return 0;
}

One of the Windows I/O models: Select 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.