手机
当前位置:查字典教程网 >编程开发 >C#教程 >基于TCP异步Socket模型的介绍
基于TCP异步Socket模型的介绍
摘要:TCP异步Socket模型C#的TCP异步Socket模型是通过Begin-End模式实现的。例如提供BeginConnect、BeginA...

TCP异步Socket模型

C#的TCP异步Socket模型是通过Begin-End模式实现的。例如提供BeginConnect、BeginAccept、 BeginSend 和 BeginReceive等。

复制代码 代码如下:

IAsyncResult BeginAccept(AsyncCallback callback, object state);

AsyncCallback回调在函数执行完毕后执行。state对象被用于在执行函数和回调函数间传输信息。

复制代码 代码如下:

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);

}

则在Accept一个TcpClient,需要维护TcpClient列表。

复制代码 代码如下:

private List<TcpClientState> clients;

异步TCP服务器完整实现

复制代码 代码如下:

/// <summary>

/// 异步TCP服务器

/// </summary>

public class AsyncTcpServer : IDisposable

{

#region Fields

private TcpListener listener;

private List<TcpClientState> clients;

private bool disposed = false;

#endregion

#region Ctors

/// <summary>

/// 异步TCP服务器

/// </summary>

/// <param name="listenPort">监听的端口</param>

public AsyncTcpServer(int listenPort)

: this(IPAddress.Any, listenPort)

{

}

/// <summary>

/// 异步TCP服务器

/// </summary>

/// <param name="localEP">监听的终结点</param>

public AsyncTcpServer(IPEndPoint localEP)

: this(localEP.Address, localEP.Port)

{

}

/// <summary>

/// 异步TCP服务器

/// </summary>

/// <param name="localIPAddress">监听的IP地址</param>

/// <param name="listenPort">监听的端口</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>

/// 服务器是否正在运行

/// </summary>

public bool IsRunning { get; private set; }

/// <summary>

/// 监听的IP地址

/// </summary>

public IPAddress Address { get; private set; }

/// <summary>

/// 监听的端口

/// </summary>

public int Port { get; private set; }

/// <summary>

/// 通信使用的编码

/// </summary>

public Encoding Encoding { get; set; }

#endregion

#region Server

/// <summary>

/// 启动服务器

/// </summary>

/// <returns>异步TCP服务器</returns>

public AsyncTcpServer Start()

{

if (!IsRunning)

{

IsRunning = true;

listener.Start();

listener.BeginAcceptTcpClient(

new AsyncCallback(HandleTcpClientAccepted), listener);

}

return this;

}

/// <summary>

/// 启动服务器

/// </summary>

/// <param name="backlog">

/// 服务器所允许的挂起连接序列的最大长度

/// </param>

/// <returns>异步TCP服务器</returns>

public AsyncTcpServer Start(int backlog)

{

if (!IsRunning)

{

IsRunning = true;

listener.Start(backlog);

listener.BeginAcceptTcpClient(

new AsyncCallback(HandleTcpClientAccepted), listener);

}

return this;

}

/// <summary>

/// 停止服务器

/// </summary>

/// <returns>异步TCP服务器</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,

HandleDatagramReceived,

internalClient);

tcpListener.BeginAcceptTcpClient(

new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);

}

}

private void HandleDatagramReceived(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,

receivedBytes, 0, numberOfReadBytes);

RaiseDatagramReceived(internalClient.TcpClient, receivedBytes);

RaisePlaintextReceived(internalClient.TcpClient, receivedBytes);

// continue listening for tcp datagram packets

networkStream.BeginRead(

internalClient.Buffer,

0,

internalClient.Buffer.Length,

HandleDatagramReceived,

internalClient);

}

}

#endregion

#region Events

/// <summary>

/// 接收到数据报文事件

/// </summary>

public event EventHandler<TcpDatagramReceivedEventArgs<byte[]>> DatagramReceived;

/// <summary>

/// 接收到数据报文明文事件

/// </summary>

public event EventHandler<TcpDatagramReceivedEventArgs<string>> PlaintextReceived;

private void RaiseDatagramReceived(TcpClient sender, byte[] datagram)

{

if (DatagramReceived != null)

{

DatagramReceived(this, new TcpDatagramReceivedEventArgs<byte[]>(sender, datagram));

}

}

private void RaisePlaintextReceived(TcpClient sender, byte[] datagram)

{

if (PlaintextReceived != null)

{

PlaintextReceived(this, new TcpDatagramReceivedEventArgs<string>(

sender, this.Encoding.GetString(datagram, 0, datagram.Length)));

}

}

/// <summary>

/// 与客户端的连接已建立事件

/// </summary>

public event EventHandler<TcpClientConnectedEventArgs> ClientConnected;

/// <summary>

/// 与客户端的连接已断开事件

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

/// 发送报文至指定的客户端

/// </summary>

/// <param name="tcpClient">客户端</param>

/// <param name="datagram">报文</param>

public void Send(TcpClient tcpClient, byte[] datagram)

{

if (!IsRunning)

throw new InvalidProgramException("This TCP server has not been started.");

if (tcpClient == null)

throw new ArgumentNullException("tcpClient");

if (datagram == null)

throw new ArgumentNullException("datagram");

tcpClient.GetStream().BeginWrite(

datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient);

}

private void HandleDatagramWritten(IAsyncResult ar)

{

((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);

}

/// <summary>

/// 发送报文至指定的客户端

/// </summary>

/// <param name="tcpClient">客户端</param>

/// <param name="datagram">报文</param>

public void Send(TcpClient tcpClient, string datagram)

{

Send(tcpClient, this.Encoding.GetBytes(datagram));

}

/// <summary>

/// 发送报文至所有客户端

/// </summary>

/// <param name="datagram">报文</param>

public void SendAll(byte[] datagram)

{

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, datagram);

}

}

/// <summary>

/// 发送报文至所有客户端

/// </summary>

/// <param name="datagram">报文</param>

public void SendAll(string datagram)

{

if (!IsRunning)

throw new InvalidProgramException("This TCP server has not been started.");

SendAll(this.Encoding.GetBytes(datagram));

}

#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

}

使用举例

复制代码 代码如下:

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<TcpDatagramReceivedEventArgs<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, TcpDatagramReceivedEventArgs<string> e)

{

if (e.Datagram != "Received")

{

Console.Write(string.Format("Client : {0} --> ",

e.TcpClient.Client.RemoteEndPoint.ToString()));

Console.WriteLine(string.Format("{0}", e.Datagram));

server.Send(e.TcpClient, "Server has received you text : " + e.Datagram);

}

}

}

【基于TCP异步Socket模型的介绍】相关文章:

基于switch你可能不知道的一些用法

C#方法的总结详解

分享C#操作内存读写方法的主要实现代码

c#数据库与TXT导入导出的实例

深入C#字符串和享元(Flyweight)模式的使用分析

关于C#生成MongoDB中ObjectId的实现方法

c#各种Timer类的区别与用法介绍

C#启动和停止windows服务的实例代码

C#异步调用的好处和方法分享

关于Flyweight模式应用实践的相关介绍

精品推荐
分类导航