Introduction to the TCP asynchronous Socket model

Source: Internet
Author: User
Tags getstream

TCP asynchronous Socket model
C #'s TCP asynchronous Socket model is implemented through the Begin-End mode. For example, BeginConnect, BeginAccept, BeginSend, and BeginReceive are provided.

Copy codeThe Code is as follows: IAsyncResult BeginAccept (AsyncCallback callback, object state );

The AsyncCallback callback is executed after the function is executed. The state object is used to transmit information between the execution function and the callback function.Copy codeThe Code is as follows: Socket socket = new Socket (
AddressFamily. InterNetwork,
SocketType. Stream,
ProtocolType. Tcp );
IPEndPoint iep = new IPEndPoint (IPAddress. Any, 8888 );
Socket. Bind (iep );
Socket. Listen (5 );
Socket. BeginAccept (new AsyncCallback (CallbackAccept), socket );

Private void CallbackAccept (IAsyncResult iar)
{
Socket server = (Socket) iar. AsyncState;
Socket client = server. EndAccept (iar );
}

You must maintain the TcpClient list in Accept.Copy codeThe Code is as follows: private List <TcpClientState> clients;

Complete asynchronous TCP server implementationCopy codeThe Code is as follows: // <summary>
/// Asynchronous TCP Server
/// </Summary>
Public class AsyncTcpServer: IDisposable
{
# Region Fields

Private TcpListener listener;
Private List <TcpClientState> clients;
Private bool disposed = false;

# Endregion

# Region Ctors

/// <Summary>
/// Asynchronous TCP Server
/// </Summary>
/// <Param name = "listenPort"> listener port </param>
Public AsyncTcpServer (int listenPort)
: This (IPAddress. Any, listenPort)
{
}

/// <Summary>
/// Asynchronous TCP Server
/// </Summary>
/// <Param name = "localEP"> listener endpoint </param>
Public AsyncTcpServer (IPEndPoint localEP)
: This (localEP. Address, localEP. Port)
{
}

/// <Summary>
/// Asynchronous TCP Server
/// </Summary>
/// <Param name = "localIPAddress"> IP address of the listener </param>
/// <Param name = "listenPort"> listener port </param>
Public AsyncTcpServer (IPAddress localIPAddress, int listenPort)
{
Address = localIPAddress;
Port = listenPort;
This. Encoding = Encoding. Default;

Clients = new List <TcpClientState> ();

Listener = new TcpListener (Address, Port );
Listener. AllowNatTraversal (true );
}

# Endregion

# Region Properties

/// <Summary>
/// Whether the server is running
/// </Summary>
Public bool IsRunning {get; private set ;}
/// <Summary>
/// IP address of the listener
/// </Summary>
Public IPAddress Address {get; private set ;}
/// <Summary>
/// Listening port
/// </Summary>
Public int Port {get; private set ;}
/// <Summary>
/// Encoding used for communication
/// </Summary>
Public Encoding {get; set ;}

# Endregion

# Region Server

/// <Summary>
/// Start the server
/// </Summary>
/// <Returns> asynchronous TCP server </returns>
Public AsyncTcpServer Start ()
{
If (! IsRunning)
{
IsRunning = true;
Listener. Start ();
Listener. BeginAcceptTcpClient (
New AsyncCallback (HandleTcpClientAccepted), listener );
}
Return this;
}

/// <Summary>
/// Start the server
/// </Summary>
/// <Param name = "backlog">
/// Maximum length of the connection sequence allowed by the server
/// </Param>
/// <Returns> asynchronous TCP server </returns>
Public AsyncTcpServer Start (int backlog)
{
If (! IsRunning)
{
IsRunning = true;
Listener. Start (backlog );
Listener. BeginAcceptTcpClient (
New AsyncCallback (HandleTcpClientAccepted), listener );
}
Return this;
}

/// <Summary>
/// Stop the server
/// </Summary>
/// <Returns> asynchronous TCP server </returns>
Public AsyncTcpServer Stop ()
{
If (IsRunning)
{
IsRunning = false;
Listener. Stop ();

Lock (this. clients)
{
For (int I = 0; I <this. clients. Count; I ++)
{
This. clients [I]. TcpClient. Client. Disconnect (false );
}
This. clients. Clear ();
}

}
Return this;
}

# Endregion

# Region Receive

Private void HandleTcpClientAccepted (IAsyncResult ar)
{
If (IsRunning)
{
TcpListener tcpListener = (TcpListener) ar. AsyncState;

TcpClient tcpClient = tcpListener. EndAcceptTcpClient (ar );
Byte [] buffer = new byte [tcpClient. ReceiveBufferSize];

TcpClientState internalClient
= New TcpClientState (tcpClient, buffer );
Lock (this. clients)
{
This. clients. Add (internalClient );
RaiseClientConnected (tcpClient );
}

NetworkStream networkStream = internalClient. NetworkStream;
NetworkStream. BeginRead (
InternalClient. Buffer,
0,
InternalClient. Buffer. Length,
Handlepolicramreceived,
InternalClient );

TcpListener. BeginAcceptTcpClient (
New AsyncCallback (HandleTcpClientAccepted), ar. AsyncState );
}
}

Private void handlepolicramreceived (IAsyncResult ar)
{
If (IsRunning)
{
TcpClientState internalClient = (TcpClientState) ar. AsyncState;
NetworkStream networkStream = internalClient. NetworkStream;

Int numberOfReadBytes = 0;
Try
{
NumberOfReadBytes = networkStream. EndRead (ar );
}
Catch
{
NumberOfReadBytes = 0;
}

If (numberOfReadBytes = 0)
{
// Connection has been closed
Lock (this. clients)
{
This. clients. Remove (internalClient );
RaiseClientDisconnected (internalClient. TcpClient );
Return;
}
}

// Received byte and trigger event notification
Byte [] receivedBytes = new byte [numberOfReadBytes];
Buffer. BlockCopy (
InternalClient. Buffer, 0,
Optional edbytes, 0, numberOfReadBytes );
RaiseDatagramReceived (internalClient. TcpClient, receivedBytes );
RaisePlaintextReceived (internalClient. TcpClient, receivedBytes );

// Continue listening for tcp datasync packets
NetworkStream. BeginRead (
InternalClient. Buffer,
0,
InternalClient. Buffer. Length,
Handlepolicramreceived,
InternalClient );
}
}

# Endregion

# Region Events

/// <Summary>
/// Receive the data packet event
/// </Summary>
Public event EventHandler <tcp1_ramreceivedeventargs <byte []> DatagramReceived;
/// <Summary>
/// Receives the datagram civilization event
/// </Summary>
Public event EventHandler <tcp1_ramreceivedeventargs <string> PlaintextReceived;

Private void raiseappsramreceived (TcpClient sender, byte [] datax)
{
If (DatagramReceived! = Null)
{
DatagramReceived (this, new tcp1_ramreceivedeventargs <byte []> (sender, datasync ));
}
}

Private void RaisePlaintextReceived (TcpClient sender, byte [] datder)
{
If (PlaintextReceived! = Null)
{
PlaintextReceived (this, new tcp1_ramreceivedeventargs <string> (
Sender, this. Encoding. GetString (datasync, 0, datax. Length )));
}
}

/// <Summary>
/// An event has been created for the connection to the client
/// </Summary>
Public event EventHandler <TcpClientConnectedEventArgs> ClientConnected;
/// <Summary>
/// The connection to the client is closed
/// </Summary>
Public event EventHandler <TcpClientDisconnectedEventArgs> ClientDisconnected;

Private void RaiseClientConnected (TcpClient tcpClient)
{
If (ClientConnected! = Null)
{
ClientConnected (this, new TcpClientConnectedEventArgs (tcpClient ));
}
}

Private void RaiseClientDisconnected (TcpClient tcpClient)
{
If (ClientDisconnected! = Null)
{
ClientDisconnected (this, new TcpClientDisconnectedEventArgs (tcpClient ));
}
}

# Endregion

# Region Send

/// <Summary>
/// Send a message to the specified Client
/// </Summary>
/// <Param name = "tcpClient"> client </param>
/// <Param name = "datax"> packets </param>
Public void Send (TcpClient tcpClient, byte [] datax)
{
If (! IsRunning)
Throw new InvalidProgramException ("This TCP server has not been started .");

If (tcpClient = null)
Throw new ArgumentNullException ("tcpClient ");

If (datasync = null)
Throw new ArgumentNullException ("datasync ");

TcpClient. GetStream (). BeginWrite (
Datax, 0, datax. Length, handleappsramwritten, tcpClient );
}

Private void handleappsramwritten (IAsyncResult ar)
{
(TcpClient) ar. AsyncState). GetStream (). EndWrite (ar );
}

/// <Summary>
/// Send a message to the specified Client
/// </Summary>
/// <Param name = "tcpClient"> client </param>
/// <Param name = "datax"> packets </param>
Public void Send (TcpClient tcpClient, string datax)
{
Send (tcpClient, this. Encoding. GetBytes (datax ));
}

/// <Summary>
/// Send messages to all clients
/// </Summary>
/// <Param name = "datax"> packets </param>
Public void SendAll (byte [] datax)
{
If (! IsRunning)
Throw new InvalidProgramException ("This TCP server has not been started .");

For (int I = 0; I <this. clients. Count; I ++)
{
Send (this. clients [I]. TcpClient, datax );
}
}

/// <Summary>
/// Send messages to all clients
/// </Summary>
/// <Param name = "datax"> packets </param>
Public void SendAll (string datax)
{
If (! IsRunning)
Throw new InvalidProgramException ("This TCP server has not been started .");

SendAll (this. Encoding. GetBytes (datax ));
}

# Endregion

# Region IDisposable Members

/// <Summary>
/// Performs application-defined tasks associated with freeing,
/// Releasing, or resetting unmanaged resources.
/// </Summary>
Public void Dispose ()
{
Dispose (true );
GC. SuppressFinalize (this );
}

/// <Summary>
/// Releases unmanaged and-optionally-managed resources
/// </Summary>
/// <Param name = "disposing"> <c> true </c> to release
/// Both managed and unmanaged resources; <c> false </c>
/// To release only unmanaged resources. </param>
Protected virtual void Dispose (bool disposing)
{
If (! This. disposed)
{
If (disposing)
{
Try
{
Stop ();

If (listener! = Null)
{
Listener = null;
}
}
Catch (SocketException ex)
{
ExceptionHandler. Handle (ex );
}
}

Disposed = true;
}
}

# Endregion
}

ExampleCopy codeThe Code is as follows: class Program
{
Static AsyncTcpServer server;

Static void Main (string [] args)
{
LogFactory. Assign (new ConsoleLogFactory ());

Server = new AsyncTcpServer (9999 );
Server. Encoding = Encoding. UTF8;
Server. ClientConnected + =
New EventHandler <TcpClientConnectedEventArgs> (server_ClientConnected );
Server. ClientDisconnected + =
New EventHandler <TcpClientDisconnectedEventArgs> (server_ClientDisconnected );
Server. PlaintextReceived + =
New EventHandler <tcp1_ramreceivedeventargs <string> (server_PlaintextReceived );
Server. Start ();

Console. WriteLine ("TCP server has been started .");
Console. WriteLine ("Type something to send to client ...");
While (true)
{
String text = Console. ReadLine ();
Server. SendAll (text );
}
}

Static void server_ClientConnected (object sender, TcpClientConnectedEventArgs e)
{
Logger. Debug (string. Format (CultureInfo. InvariantCulture,
"TCP client {0} has connected .",
E. TcpClient. Client. RemoteEndPoint. ToString ()));
}

Static void server_ClientDisconnected (object sender, TcpClientDisconnectedEventArgs e)
{
Logger. Debug (string. Format (CultureInfo. InvariantCulture,
"TCP client {0} has disconnected .",
E. TcpClient. Client. RemoteEndPoint. ToString ()));
}

Static void server_PlaintextReceived (object sender, tcp1_ramreceivedeventargs <string> e)
{
If (e. datax! = "Received ")
{
Console. Write (string. Format ("Client: {0} --> ",
E. TcpClient. Client. RemoteEndPoint. ToString ()));
Console. WriteLine (string. Format ("{0}", e. Dateline ));
Server. Send (e. TcpClient, "Server has sent ed you text:" + e. datax );
}
}
}

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.