In. NET Framework 2.0, the system. net. Sockets namespace provides a socket class with almost all functions of Windows Winsock Win32 API. The class to which this feature belongs contains various methods and attributes designed for hosted code developers. On the socket, there is a set of synchronization methods, including send and receive, with parameter overloading for various situations. These synchronization methods are not only easy to use, but also very suitable for simple network tasks that use sockets. There is also a set of asynchronous methods based on the asynchronous programming model (APM) on the socket, APM is very common in. NET Framework (for more information, see msdn.microsoft.com/msdnmag/issues/07/03/concurrentaffairs ). These asynchronous methods make the asynchronous use of socket classes relatively simple, and also provide a method to process many sockets, or to process multiple sending and receiving operations on many sockets.
The 2.0 socket class is suitable for a variety of client applications that require network sockets, as well as some server and service applications. Unfortunately, some service application solutions are not applicable to socket classes of Version 2.0, but are compatible with local languages that directly use Windows Winsock APIs. The main problem with the socket class of Version 2.0 is that it not only allocates necessary basic objects to maintain I/O operations on a large number of sockets, but also occupies an excessive CPU cycle, this is also true when performing a single socket I/O operation.
With. NET Framework 3.5, the Common Language Runtime (CLR) can more effectively manage a large number of overlapped objects at the same time. The overlapped object in CLR can effectively encapsulate the local Windows overlapped structure used to manage asynchronous I/O operations. Each ongoing socket asynchronous I/O operation has an overlapped object instance. Now we can have 60 thousand or more connection sockets, and keep a suspended asynchronous receiving I/O operation on each socket.
2.0 socket class uses Windows I/O to complete port asynchronous I/O operations. This allows applications to easily expand to a large number of open sockets .. NET framework implements the system. Threading. threadpool class, which provides a thread that can read and complete ports and complete asynchronous I/O operations. In the development of the forthcoming version 3.5. in the process of Net Framework, we put a lot of effort into eliminating the overhead in the code path, this includes the signal between reading the completion port and calling the application's completion proxy or sending an I/O completion event object in the iasyncresult object.
APM in. NET Framework is also called the begin/end mode. This is because the begin method is called to start asynchronous operations and an iasyncresult object is returned. You can provide a proxy as a parameter to the begin method. This method is called when asynchronous operations are completed. Alternatively, a thread can wait for iasyncresult. asyncwaithandle. When a callback is called or a waiting signal is sent, the end method is called to obtain the asynchronous operation result. This mode is flexible and easy to use, which is very common in. NET Framework.
However, you must note that a large number of asynchronous socket operations are costly. For each operation, an iasyncresult object must be created and cannot be reused. Because a large amount of object allocation and garbage collection are used, this will affect the performance. To solve this problem, the new version provides another method that uses sockets to execute asynchronous I/O. This new mode does not require the allocation of Operation context objects for each socket operation.
We didn't create a new mode, but just used the existing mode and made a basic change. Now, there are some methods in the socket class that use the event-based variant to complete the model. In version 2.0, you can use the following code to start asynchronous sending on a socket:
Void onsendcompletion (iasyncresult AR ){}
Iasyncresult AR = socket. beginsend (buffer, 0, buffer. length, socketflags. None, onsendcompletion, State );
In the new version, you can also:
Void onsendcompletion (Object SRC, socketasynceventargs SAE ){}
Socketasynceventargs SAE = new
Socketasynceventargs ();
Sae. Completed + = onsendcompletion;
Sae. setbuffer (buffer, 0, buffer. Length );
Socket. sendasync (SAE );
There are some obvious differences here. The encapsulated operation context is a socketasynceventargs object, not an iasyncresult object. This application creates and manages (or even can be reused) socketasynceventargs objects. All parameters of the socket operation are specified by the attributes and methods of the socketasynceventargs object. The completion status is also provided by the attributes of the socketasynceventargs object. Finally, you need to use the event processing program callback to complete the method.
All these changes have significantly improved the performance and scalability of the system. net. Sockets class in. NET Framework 3.5. Existing applications can automatically implement two improvements. The third improvement, namely, the new socket method, can only be used by modifying the application, but these methods can provide better scalability for socket-based demanding applications.
An example of a TCP version of echoserver is as follows:
Class
Echoserver
{
Socket server;
Public echoserver (ipendpoint localpoint)
{
Server = new
Socket (localpoint. addressfamily, sockettype. Stream, protocoltype. TCP );
Server. BIND (localpoint );
Server. Listen (5 );
Accept_async ();
}
Private
Void accept_async ()
{
VaR accept = new
Socketasynceventargs ();
Accept. Completed + = accept_completed;
Server. acceptasync (accept );
}
Void accept_completed (Object sender, socketasynceventargs E)
{
Accept_async ();
VaR client = E. acceptsocket;
E. Completed-= accept_completed;
E. Completed + = receive_completed;
VaR buffer = new
Byte [2, 1024];
E. setbuffer (buffer, 0, buffer. Length );
Client. receiveasync (E );
}
Void receive_completed (Object sender, socketasynceventargs E)
{
VaR client = sender
Socket;
If (E. bytestransferred = 0)
{
Console. writeline ("socket is closed ");
Client. Close ();
}
Else
{
Client. Send (E. buffer, E. bytestransferred, socketflags. None );
Client. receiveasync (E );
}
}
}
Reference: http://msdn.microsoft.com/zh-cn/magazine/cc163356.aspx