Writing network services on. NET is 2, 3 years old, and how these times are. NET has accumulated some experience in the implementation of network services. In the next time, this experience will be shared through the blog. And this chapter is mainly about the efficiency of service connection access, so that the concurrency of Service connection access has high throughput performance.
In fact. NET provides a very powerful network model for us to use, And we just need to use this model well. That's based on the fact that there is no big problem. However, since many developers do not understand and delve into this aspect, it is difficult to feel. NET to write a high-performance service. The following examples are used to describe where the problem is and to avoid these problems and to make the services you write more efficient.
Example 1
try {Listener. Bind (Localendpoint); Listener. Listen (10); Start listening for connections. while (true) {Console.WriteLine ("Waiting for a Connection ..."); Program is suspended and waiting for an incoming connection. Socket handler = listener. Accept (); data = null; An incoming connection needs to be processed. while (true) {bytes = new byte[1024]; int Bytesrec = handler. Receive (bytes); Data + = Encoding.ASCII.GetString (Bytes,0,bytesrec); if (data. IndexOf ("<EOF>") >-1) {break; }}//Show the data on the console. Console.WriteLine ("Text Received: {0}", data); Echo the data back to the client. byte[] msg = Encoding.ASCII.GetBytes (data); Handler. Send (msg); Handler. Shutdown (Socketshutdown.both); Handler. Close (); }} catch (Exception e) {Console.WriteLine (e.tostring ()); }
This is a server-side example from MSDN with the Code address source Http://msdn.microsoft.com/en-us/library/6y0e13d3 (v=vs.110). aspx above the code to tell the truth really does not have much reference meaning, However, as a demonstration of how to build a service listener that still plays a role, it is completely impractical to use in server applications, because this only causes the session to be serial, and only one can be processed. Next, look for an example that supports connection concurrency on the internet.
Example 2
Namespace Socketserver{class Program {private static byte[] result = new byte[1024]; private static int myprot = 8885; Port static Socket ServerSocket; static void Main (string[] args) {//server IP address IPAddress ip = ipaddress.parse ("127.0.0.1"); ServerSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, protocoltype.tcp); Serversocket.bind (New IPEndPoint (IP, Myprot)); Bind IP Address: Port Serversocket.listen (10); Set up to 10 queued connection requests Console.WriteLine ("Boot listener {0} succeeded", ServerSocket.LocalEndPoint.ToString ()); Send data via clientsoket thread myThread = new Thread (listenclientconnect); Mythread.start (); Console.ReadLine (); }///<summary>//Monitoring Client connection///</summary> private static void Listenclientconnect () {while (true) {Socket Clientsocket = ServerSocket.Accept (); Clientsocket.send (Encoding.ASCII.GetBytes ("Server Say Hello")); Thread receivethread = new Thread (ReceiveMessage); Receivethread.start (Clientsocket); }}///<summary>//Reception///</summary>//<param name= "Clientsocket" ></param> private static void ReceiveMessage (object clientsocket) {Socket Myclientsocke t = (Socket) clientsocket; while (true) {... int receivenumber = myclientsocket.receive (result); Console.WriteLine ("Receive client {0} message {1}", MyClientSocket.RemoteEndPoint.ToString (), Encoding.ASCII.GetString (result, 0, Receivenumber)); } } }}
The above example can accept multiple connections for processing at the same time, but the disadvantage is that it is very obvious that this approach is not possible if the number of connections supported by the service is larger. You know, if this server is going to support 1w,3w or 10W connections, how many threads do you need to open to handle these connections, Even if you can do that, the overhead of the thread is enough to make the server suffer. Next look at the asynchronous example provided by MSDN
Example 3
while (true) {//Set the event to nonsignaled state. Alldone.reset (); Start an asynchronous socket to listen for connections. Console.WriteLine ("Waiting for a Connection ..."); Listener. BeginAccept (New AsyncCallback (Acceptcallback), listener); Wait until a connection is made before continuing. Alldone.waitone (); } public static void Acceptcallback (IAsyncResult ar) {//Signal the main thread to continue. Alldone.set (); Get the socket that handles the client request. Socket listener = (socket) ar. asyncstate; Socket handler = listener. Endaccept (AR); Create the state object. StateObject state = new StateObject (); State.worksocket = handler; Handler. BeginReceive (state.buffer, 0, stateobject.buffersize, 0, New AsyncCallback (Readcallback), state); }
This example is derived from Http://msdn.microsoft.com/en-us/library/6y0e13d3 (v=vs.110). aspx, In fact, this code is very efficient embodiment of how we write services when the implementation of an access monitoring. This example is fully qualified for application development.
Improved
Example 3 above has already provided very good code, that can make some specification improvement. In fact, in the past experience is possible, first of all we understand. NET has two threads, one that we often use and the other is the IO thread. In fact, with some test tools you can see that acceptcallback is an IO thread callback, we want the callback thread to be released faster, So we need to do some isolation planning. In fact, in many sample code is a series of events to complete, access----receive-and-send. Such a coherent code implementation causes the control and planning of its thread resources to become very difficult.
From the design of the code, you can isolate the work that the callback thread needs through the queue, allowing the callback thread to come back faster to handle its access work. When isolated, even later connection access requires some logical control that does not affect the fast regression of the callback thread. This makes the entire asynchronous thread resource more efficient.
public static void Acceptcallback (IAsyncResult ar) { //Signal The main thread to continue. Alldone.set (); Get the socket that handles the client request. Socket listener = (socket) ar. asyncstate; Socket handler = listener. Endaccept (AR); Queue.enqueue (handler); }
Summarize
In fact, the queue separation and control in the entire network communication implementation process will be used frequently, its main purpose is to deal with the resources of the block and thread resource control. After all, the resources of any one server is limited, how to allocate the thread resources to the different any to complete the work is very important, after all, the overhead of a large number of threads will cause .
. NET socket Service Programming-efficient connection Access codec