C # Implementation of multithreaded asynchronous socket packet receiver framework

Source: Internet
Author: User
Tags net thread

A few days ago in the Bo asked to see a C # Socket problem, think of the author 2004 to do a provincial traffic flow receiving server project, the basic request is as follows: Receive automatic observation equipment through wireless network card, internet and socket reported traffic volume data packets year-round 365* 24 operation of automatic observation equipment 5 minutes to report observation data, each record about 2K size planning province will have about 100 automatic observation equipment (as of October 2008 and only 30)

At that time, VS2003 was released more than a year, the author is also contact C # soon. So Google the domestic and foreign network, hope to find a point to apply C # to solve socket communication problems and code. Finally, found two articles to help the largest article: one is written by the Chinese socket receiver framework, the application of the independent client socket session (sessions) concept, to provide the author a general framework for the reception server ideas; another is written by the Americans, put forward the multithreading, The technical scheme of packet receiving packet, describes many implementation details of multithread and asynchronous socket, and this paper has determined the technical route of processing socket receiver with multithreading and asynchronous method.

The implementation and testing of the author also found that in the Internet environment in the socket application, the need for the system has a strong fault tolerance: no way to control the exception, you must allow them to exist (additional source code can be seen, try{}catch{} statements). In this respect, the author designed a special inspection and cleaning thread, complete invalid or timeout session cleanup and resource release work.

Vaguely remember that the domestic framework of the author's namespace has IBM, think of IBM employees, through the mail before they know that the person in Shenzhen. The author consulted several questions to him and discussed several technical key points with each other. Unfortunately, now to find, has not been found in the original text and mail. Have to take this opportunity, this document to the two never met the technical expert and peer, but also hope that the humble text or source can give readers a little useful inspiration and help.

1. Main technical Ideas

The entire system consists of three core threads, and consists of. NET thread Pooling Unified management: listening Client connection request thread:listenclientrequest (), looping listening for client connection requests. If so, detect the client IP to see if it is the same observation device, then establish a client TSession object and call the method asynchronously via the socket BeginReceive () receive the packet, endreceive () to process the packet packet processing thread: handledatagrams (), loop detection packet queue _datagramqueue, complete packet parsing, judgment type, storage and other work client status detection thread:checkclientstate (), Loop Check client session table _sessiontable, determine if Session object is valid, set timeout session shutdown flag, clear Invalid Session object and release its resources

2. Introduction to main categories

The system is mainly composed of 3 classes: tdatagramreceiver(Packet receiving server): The core process class of the system, establishing socket connection, processing and storing packets, cleaning up system resources, this class provides all public properties and methods TSession(client session): A socket object that consists of each client, has its own data buffer, and the cleanup thread determines whether to timeout Tdatagram(Packet Class) based on the most recent session time of the object: Determining packet categories, parsing packets

3. Key functions and codes

The key implementation code for the core class Tdatagramreceiver is briefly shown below.

3.1 System Startup

The system startup Method Startreceiver () First cleans up the resource, creates a database connection, initializes several count values, and then creates a server-side listening socket object, and finally calls the static method ThreadPool.QueueUserWorkItem () Create 3 core processing threads in the thread pool. Code

Code highlighting produced by Actipro Codehighlighter (freeware)
http://www.CodeHighlighter.com/

-->///<summary>
Start the receiver
</summary>
public bool Startreceiver ()
{
Try
{
_stopreceiver = true;

This. Close ();

if (!this. Connectdatabase ()) return false;

_clientcount = 0;
_datagramqueuecount = 0;
_datagramcount = 0;
_errordatagramcount = 0;
_exceptioncount = 0;

_sessiontable = new Hashtable (_maxallowclientcount);
_datagramqueue = new queue<tdatagram> (_maxallowdatagramqueuecount);

_stopreceiver = false; This flag is needed in the loop

if (!this. Createreceiversocket ())//Establish a server-side Socket object
{
return false;
}

Listens for client connection request threads, uses delegate inference, does not build CallBack objects
if (! ThreadPool.QueueUserWorkItem (Listenclientrequest))
{
return false;
}

Processing packet Queue Threads
if (! ThreadPool.QueueUserWorkItem (Handledatagrams))
{
return false;
}

Check the client session state and clear the object for a long time without communication
if (! ThreadPool.QueueUserWorkItem (checkclientstate))
{
return false;
}

_stopconnectrequest = false; Start the receiver, the connection is automatically allowed
}
Catch
{
This. Onreceiverexception ();
_stopreceiver = true;
}
return!_stopreceiver;
}

The following is a method code to create a listening socket object. Code

Code highlighting produced by Actipro Codehighlighter (freeware)
http://www.CodeHighlighter.com/

-->///<summary>
Create a Socket for the receiving server and listen for client connection requests
</summary>
private bool Createreceiversocket ()
{
Try
{
_receiversocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, protocoltype.tcp);
_receiversocket.bind (New IPEndPoint (Ipaddress.any, _tcpsocketport)); Binding ports
_receiversocket.listen (_maxallowlistenqueuelength); Start listening.

return true;
}
Catch
{
This. Onreceiverexception ();
return false;
}
}

3.2 Listening for client connection requests

The server-side loop waits for a client connection request. Once the request, first determine whether the client connection is overrun, then detect the client IP address, all normal after the establishment of the TSession object, and call the asynchronous method to receive the client socket packets.

In code, the callback AsyncCallback Delegate Method Endreceivedata () completes data reception when the socket reads data, and normally initiates another asynchronous BeginReceive () call.

. NET, each asynchronous method has its own independent thread, and asynchronous processing is actually based on multithreading. Asynchronous sets in the following code asynchronous calls, not only occupy a large system resources, but also to deal with unexpected results, but the exception is difficult to control and deal with the key. Code

Code highlighting produced by Actipro Codehighlighter (freeware)
http://www.CodeHighlighter.com/

-->///<summary>
Circular listening for client requests, with a single parameter due to the thread pool
</summary>
private void Listenclientrequest (object state)
{
Socket client = null;
while (!_stopreceiver)
{
if (_stopconnectrequest)//Stop Client connection requests
{
if (_receiversocket!= null)
{
Try
{
_receiversocket.close (); Force shutdown Receiver
}
Catch
{
This. Onreceiverexception ();
}
Finally
{
Must be null, otherwise the disposed object still exists and the following error will be raised
_receiversocket = null;
}
}
Continue
}
Else
{
if (_receiversocket = null)
{
if (!this. Createreceiversocket ())
{
Continue
}
}
}

Try
{
if (_receiversocket.poll (_loopwaittime, Selectmode.selectread))
{
Frequent shutdown, startup, error prone here (prompt socket can only have one)
Client = _receiversocket.accept ();

if (client!= null && client. Connected)
{
if (This._clientcount >= this._maxallowclientcount)
{
This. Onreceiverexception ();

Try
{
Client. Shutdown (Socketshutdown.both);
Client. Close ();
}
Catch {}
}
else if (checksameclientip (client))//The IP address already exists
{
Try
{
Client. Shutdown (Socketshutdown.both);
Client. Close ();
}
Catch {}
}
Else
{
TSession session = new tsession (client);
Session. Logintime = DateTime.Now;

Lock (_sessiontable)
{
int presessionid = session.id;
while (true)
{
if (_sessiontable.containskey (session.id))//It is possible to repeat the number
{
Session.id = 100000 + Presessionid;
}
&nbs

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.