// 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!