Windows Network Programming-Winsock (iii) non-blocking select Mode Server

Source: Internet
Author: User
Tags set set set socket time in milliseconds

// Selectmodewinsock. cpp: defines the entry point of the console application.
//
/************************************
Author: wangweixing2000
Revision by: 0.01
Revised on 2005-6-29 11:52:03
Comments: selectmodewinsock this program has a bug. It does not handle multi-threaded Data Access conflicts and determines the effective handling of client disconnections! Which of the following can be added if you are interested!

************************************/
// Select model: uses the select function to manage I/O. The select function can be used
// Determine whether data exists on the socket or whether data can be written to a socket.
/*
Int select (
Int NFDs, // this parameter is reserved to maintain compatibility with earlier Berkeley socket applications.
Fd_set * readfds, // check the readability fd_set * Parameter
Fd_set * writefds, // check the writable fd_set * Parameter
Fd_set * contains TFDs, // out-of-band data
Const struct timeval * timeout // specifies the maximum length of time the SELECT statement can wait for the I/O operation to complete.
);

Typedef struct timeval
{
Long TV _sec; // specify the waiting time in seconds
Long TV _usec; // The specified wait time in milliseconds
} Timeval;
Before using select to listen to a socket, the application must allocate the socket handle to a set and set one or all the read, write, and exception
Fd_set structure. Assign a socket to any set and then call select to check whether I/O activity is ongoing on a socket.

Winsock provides several macros to process fd_set:
Fd_zero (* Set) // clear fd_set *
Fd_clr (S, * Set) // Delete s socket from set
Fd_isset (S, * Set) // check whether s is a member of the Set set. If yes, true is returned.
Fd_set (S, * Set) // set socket s to join the set
*/
# Include "stdafx. H"
# Include <iostream>
# Include <winsock2.h>
# Include <ws2tcpip. h>
# Pragma comment (Lib, "ws2_32.lib ")
Using namespace STD;
Struct socketobj
{
Socket socket; // The socket of the current object
Bool listening; // whether the socket has been
Socketobj * Next, // backward
* Prev; // forward
};
Socketobj * g_psocketlist = NULL; // socket table
Socketobj * g_psocketend = NULL; // end of the connected table
Int g_nsocketcount = 0;
Handle g_hselect;

// Create socketobj
Socketobj * getsocketobj (socket S, bool listening)
{
Socketobj * newsocketobj = NULL;
Newsocketobj = (socketobj *) heapalloc (getprocessheap (), heap_zero_memory, sizeof (socketobj ));
If (newsocketobj = NULL)
{
Cout <"getsocketobj: heapalloc failed:" <getlasterror () <Endl;
Exitprocess (-1); // end the process
}
Newsocketobj-> socket = s;
Newsocketobj-> listening = listening;
Return newsocketobj;
}

// Insert a socketobj
Void insersocketobj (socketobj * OBJ)
{
OBJ-> next = obj-> Prev = NULL;
If (g_psocketlist = NULL)
{
G_psocketlist = g_psocketend = OBJ;
}
Else
{
OBJ-> Prev = g_psocketend;
G_psocketend-> next = OBJ;
G_psocketend = OBJ;
}
G_nsocketcount ++;
}
// Delete
Void removesocketobj (socketobj * OBJ)
{
If (obj-> PREV)
{
OBJ-> Prev-> next = obj-> next;
}
If (obj-> next)
{
OBJ-> next-> Prev = obj-> Prev;
}
If (OBJ = g_psocketlist)
{
G_psocketlist = obj-> next;
}
If (OBJ = g_psocketend)
{
G_psocketend = obj-> Prev;
}
G_nsocketcount --;
Heapfree (getprocessheap (), 0, OBJ );
}
// Listening thread
DWORD winapi listenthread (void * pvoid)
{
Cout <"Server start listening! "<Endl;

Sockaddr_in clientaddr; // defines the address structure of a client as a parameter.
Int addr_length = sizeof (clientaddr );
Socket * Listen = (socket *) pvoid;
Socketobj * psocketobj = NULL;
While (1)
{
Socket Client = accept (* Listen, (sockaddr *) & clientaddr, & addr_length );
If (client = invalid_socket)
{
Cout <"Accept failed! "<Endl;
Continue;
}
// The IP address and port of the client can be obtained here, but we only take the socket number
Lpctstr lpip = inet_ntoa (clientaddr. sin_addr );
Uint nport = clientaddr. sin_port;
Cout <"A client has been connected! IP: "<lpip <" socket port: "<nport <Endl;
// Create socketobj and add it, as shown in list
Psocketobj = getsocketobj (client, true );
Insersocketobj (psocketobj );
If (g_nsocketcount = 1) // If a client is present, the Select thread is invoked.
{
Resumethread (handle) g_hselect );
}
}
Return 0;
}
// Select thread function
DWORD winapi selectthread (void * pvoid)
{
Socketobj * sptr = NULL;
Fd_set readfds,
Writefds,
Required TFDs;
Timeval timeout;
Char buffer [4096];
While (true)
{
// Clear fd_set
Fd_zero (& readfds );
Fd_zero (& writefds );
Fd_zero (& exceptfds );

// Set timeout
Timeout. TV _sec = 5;
Timeout. TV _usec = 0;

Sptr = g_psocketlist;
// Set fd_set
While (sptr)
{
Fd_set (sptr-> socket, & readfds );
Fd_set (sptr-> socket, & writefds );
Fd_set (sptr-> socket, & Other TFDs );
Sptr = sptr-> next;
}

// Start select
Int ret = select (0, & readfds, & writefds, null, & timeout );
If (ret = socket_error)
{
Cout <"select failed! "<Endl;
Wsacleanup ();
Return-1;
}
Else if (ret = 0)
{
// Timeout
Cout <"time out! "<Endl;
Continue;
}
Else
{
Sptr = g_psocketlist;
While (sptr)
{
If (fd_isset (sptr-> socket, & readfds ))
{
Zeromemory (buffer, 4096 );
Int Re = Recv (sptr-> socket, buffer, 4096, 0 );
If (RE = socket_error)
{
Return-1;
}
Else if (RE = 0)
{
// The client has been disconnected.
Closesocket (sptr-> socket );
Socketobj * TMP = sptr;
Sptr = sptr-> next;
Removesocketobj (TMP );
Continue;
}
Else
{
Cout <"Recv Buffer:" <buffer <Endl;
}
}
If (fd_isset (sptr-> socket, & writefds ))
{
// Send data to the current client
Char * sendbuffer = "wwx send MSG! ";
Int Re = Send (sptr-> socket, sendbuffer, 16, 0 );
If (RE = socket_error)
{
Return-1;
}
Else if (RE = 0)
{
Continue;
}
Else
{
// Check whether the message is sent successfully.
// Cout <"Send successed! "<Endl;
}
}
Sptr = sptr-> next;
}
}
}

Return 0;
}
Int _ tmain (INT argc, _ tchar * argv [])
{
Wsadata;
Socket listen;
Socketobj * psockobj = NULL;
Socket accept = invalid_socket;
Sockaddr_in serveraddr;
 

// Initialize the Winsock Library
Int ret = wsastartup (makeword (2, 2), & wsadata );
If (Ret! = 0)
{
Cout <"wsastartup error! "<Endl;
Wsacleanup ();
Return-1;
}
 
Listen = socket (af_inet, sock_stream, ipproto_tcp );
If (Listen = invalid_socket)
{
Cout <"Listen create failed! "<Endl;
Wsacleanup ();
Return-1;
}

// Bind
Serveraddr. sin_family = af_inet;
Serveraddr. sin_addr.s_un.s_addr = htonl (inaddr_any );
Serveraddr. sin_port = htons (10012 );
Ret = BIND (Listen, (sockaddr *) & serveraddr, sizeof (sockaddr_in ));
If (ret = socket_error)
{
Cout <"bind failed! "<Endl;
Closesocket (Listen );
Wsacleanup ();
Return-1;
}

// Listen
Listen (Listen, 200 );
 
// Enable the listening thread
Handle hlisten = createthread (null, 0, listenthread, & listen, 0, null );
If (hlisten = NULL)
{
Cout <"create listenthread failed! "<Endl;
}
// The select thread suspended by the price creation, because the client is not connected at the beginning
G_hselect = createthread (null, 0, selectthread, null, create_suincluded, null );
If (g_hselect = NULL)
{
Cout <"create selectthread failed! "<Endl;
}
System ("pause ");
Return 0;
}

If you reference this article, please indicate the source! Thank you!

Related Article

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.