Learning and testing the select model of WinSock I/O

Source: Internet
Author: User
Tags htons

# Include <winsock2.h>
# Include <stdio. h>
# Include <windows. h>
# Pragma comment (Lib, "ws2_32.lib ")

Bool insertsock (socket * psock, socket sock)
{
For (INT nindex = 0; nindex <fd_setsize-1; nindex ++)
{
If (psock [nindex] = invalid_socket)
{
Psock [nindex] = sock;
Break;
}
}
 
If (nindex = fd_setsize-1)
Return false;

Return true;
}

 

Int main (INT argc, char * argv [])
{
 
Wsadata;
Word sockversion = makeword (2, 0 );
Wsastartup (sockversion, & wsadata );

Socket clientsockarray [fd_setsize-1];
Socket S = socket (af_inet, sock_stream, ipproto_tcp );
If (S = invalid_socket)
{
Printf ("failed socket ()/n ");
Wsacleanup ();
Return 0;
}

Sockaddr_in sin;
Sin. sin_family = af_inet;
Sin. sin_port = htons (8888 );
Sin. sin_addr.s_un.s_addr = inaddr_any;

If (BIND (S, (lpsockaddr) & sin, sizeof (SIN) = socket_error)
{
Printf ("failed BIND () % d/N", getlasterror ());
Wsacleanup ();
Return 0;
}

If (Listen (S, 63) = socket_error)
{
Printf ("failed listen ()/n ");
Wsacleanup ();
Return 0;
}

For (INT I = 0; I <64; I ++)
{
Clientsockarray [I] = invalid_socket;
}

Sockaddr_in remoteaddr;
Int naddrlen = sizeof (remoteaddr );

// Char sztext [] = "Hello world! ";
Fd_set FD;
Fd_zero (& FD );
Timeval TV = {30, 0 };
Fd_set (S, & FD );

Printf ("Server start: % d/N", getlasterror ());
Int num = 0;
While (true)
{
Int nresult;
Nresult = select (0, & FD, null, null, & TV );
If (nresult = socket_error)
{
Printf ("select failed/N ");
Continue;
}
/*
If (nresult> 0)
{
Printf ("dddddddddd/N ");
}
*/

If (fd_isset (S, & FD ))
{
Socket Client;
Client = accept (S, (sockaddr *) & remoteaddr, & naddrlen );
If (client = invalid_socket)
{
Printf ("client connect fail % d", getlasterror ());
Continue;
}
If (! Insertsock (clientsockarray, client ))
{
Printf ("too many sockets × ó ''socket/N ");
Closesocket (client );
Continue;
}
Fd_set (client, & FD );
}
// Öð omö' ¦ fií'ó óú' ý ö ö×' ì µ µäì × ½ óxö

Nresult = select (0, & FD, null, null, & TV );
If (nresult = socket_error)
{
Printf ("select failed/N ");
Continue;
}

For (INT nindex = 0; nindex <= fd_setsize-1; nindex ++)
{
If (fd_isset (clientsockarray [nindex], & FD ))
{
// Printf ("AAAA/N ");
Char buffer [256];
Int nret = Recv (clientsockarray [nindex], buffer, sizeof (buffer), 0 );
If (nret = 0 | nret = socket_error)
{
Closesocket (clientsockarray [nindex]);
Clientsockarray [nindex] = invalid_socket;
Continue; // ¼ ì ð ø '**************************************
}
// When «ó ê ü μ µ äê ö ø?
// Char buffer [256];
// Recv (clientsockarry [nindex], buffer, 256 );
Printf ("has Recv data from socket % d: % s", I, buffer );
Printf ("Num: % d/N", ++ num );
}
}

}

Closesocket (s );
Wsacleanup ();
Return 0;

}

 

An example is provided ,,

The following code is a multi-connection application established in select, which is an I/O model. Can work normally.
But there are some problems. After accepting 2 or more connections, the data sent by these connections is always received, which is unstable.
For example;
After accepting three connections.
1. Connect to send data 11111.
Display 11111.
2 connection sends 22222.
Show 22222
Run one task.
3. The connection sends 33333 messages.
Display is
3
3
3
3
3. After 5 rounds, the data is received separately.

I don't understand why the program becomes unstable?
Why does one piece of data always count, one byte or one byte?
Why does the message always receive null messages?
Where is it not handled?

The Code is as follows:

// Select I/O model

# Include <stdio. h>
# Include <winsock2.h>

# Pragma comment (Lib, "ws2_32 ")

Int ret;

Int main ()
{
Ushort nport = 12345; // The port number that the server listens

Wsadata;

If (wsastartup (0x0202, & wsadata )! = 0)
{
Printf ("wsastartup error! /N ");
Getchar ();
Return 0;
}

// Create a listening set of characters
Socket 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 the character set to the Local Machine
If (BIND (slisten, (sockaddr *) & sin, sizeof (SIN) = socket_error)
{
Printf ("failed BIND ()/n ");
Return 0;
}

If (Listen (slisten, 5 ))
{
Printf ("Listen error! /N ");
Getchar ();
Return 0;
}

// --------------------------------------------------- It seems that the setting of this mode is necessary.
Ulong nonblock = 1;
If (ioctlsocket (slisten, fionbio, (u_long *) & nonblock) = socket_error)
{
Printf ("ioctlsocket () failed with error % d/N", wsagetlasterror ());
Getchar ();
Return 0;
}
//----------------------------------------------------

// Select model processing process
// 1) initialize a set of characters fdsocket and add a listening set of character handles to this set.
Fd_set fdsocket; // a collection of all applicable sets of Characters
Fd_zero (& fdsocket );
Fd_set (slisten, & fdsocket );

While (true)
{
Ret = printf ("/n big while -----------------------! /N ");

// 2) pass a copy of The fdsocket set fdread to the select function,
// When an event occurs, the Select function removes the character handle that has no pending I/O operations in the fdread set and returns the result.
Fd_set fdread = fdsocket;
Int nret = select (0, & fdread, null );

If (nret> 0)
{
// 3) Compare the fdread set processed by the SELECT statement with the fdsocket set,
// Determine which sets of knots are pending I/O and further process these I/O.
For (INT I = 0; I <(INT) fdsocket. fd_count; I ++)
{
Ret = printf ("/n big! /N ");
If (fd_isset (fdsocket. fd_array [I], & fdread ))
{
If (fdsocket. fd_array [I] = slisten) // (1) Listen to the set of characters to receive new connections
{
If (fdsocket. fd_count <fd_setsize)
{
Sockaddr_in addrremote;
Int naddrlen = sizeof (addrremote );
Socket snew =: accept (slisten, (sockaddr *) & addrremote, & naddrlen );
Fd_set (snew, & fdsocket );
Printf ("received connection (% s)/n",: inet_ntoa (addrremote. sin_addr ));
}
Else
{
Printf ("too much connections! /N ");
Continue;
}
}
Else
{
Char sztext [256];
Int nrecv =: Recv (fdsocket. fd_array [I], sztext, sizeof (sztext), 0 );
If (nrecv> 0) // (2) readable
{
Sztext [nrecv] = '/0 ';
Printf ("received data: % s/n", sztext );
}
Else // (3) the connection is closed, restarted, or interrupted.
{
: Closesocket (fdsocket. fd_array [I]);
Fd_clr (fdsocket. fd_array [I], & fdsocket );
}
}
}
}
}
Else
{
Printf ("failed select ()/n ");
Break;
}
}
Return 0;
}

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.