本文介绍
TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。 可使用 TcpClient 或 Socket 来连接 TcpListener。 可使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener。 可以将本地 IP 地址指定为 Any,将本地端口号指定为 0(如果希望基础服务提供程序为您分配这些值)。
如果您选择这样做,可在连接套接字后使用 LocalEndpoint 属性来标识已指定的信息。使用 Start 方法,可开始侦听传入的连接请求。 Start 将对传入连接进行排队,直至您调用 Stop 方法或它已经完成 MaxConnections 排队为止。 可使用 AcceptSocket 或 AcceptTcpClient 从传入连接请求队列提取连接。 这两种方法将阻止。 如果要避免阻止,可首先使用 Pending 方法来确定队列中是否有可用的连接请求。
虽然tcplistener已经封装的比较不错了,我们于是就使用它在构造一个比较不错的异步tcp服务器,这里依然和前两章一样,给出服务器中的代码,代码中注释很详细,我也会给出相关的封装类。
TcpListener异步TCP服务器
服务器代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace NetFrame.Net.TCP.Listener.Asynchronous
{
///
/// TcpListener实现异步TCP服务器
///
public class AsyncTCPServer : IDisposable
{
#region Fields
///
/// 服务器程序允许的最大客户端连接数
///
private int _maxClient;
///
/// 当前的连接的客户端数
///
private int _clientCount;
///
/// 服务器使用的异步TcpListener
///
private TcpListener _listener;
///
/// 客户端会话列表
///
private List _clients;
private bool disposed = false;
#endregion
#region Properties
///
/// 服务器是否正在运行
///
public bool IsRunning { get; private set; }
///
/// 监听的IP地址
///
public IPAddress Address { get; private set; }
///
/// 监听的端口
///
public int Port { get; private set; }
///
/// 通信使用的编码
///
public Encoding Encoding { get; set; }
#endregion
#region 构造函数
///
/// 异步TCP服务器
///
/// 监听的端口
public AsyncTCPServer(int listenPort)
: this(IPAddress.Any, listenPort)
{
}
///
/// 异步TCP服务器
///
/// 监听的终结点
public AsyncTCPServer(IPEndPoint localEP)
: this(localEP.Address, localEP.Port)
{
}
///
/// 异步TCP服务器
///
/// 监听的IP地址
/// 监听的端口
public AsyncTCPServer(IPAddress localIPAddress, int listenPort)
{
Address = localIPAddress;
Port = listenPort;
this.Encoding = Encoding.Default;
_clients = new List();
_listener = new TcpListener(Address, Port);
_listener.AllowNatTraversal(true);
}
#endregion
#region Method
///
/// 启动服务器
///
public void Start()
{
if (!IsRunning)
{
IsRunning = true;
_listener.Start();
_listener.BeginAcceptTcpClient(
new AsyncCallback(HandleTcpClientAccepted), _listener);
}
}
///
/// 启动服务器
///
///
/// 服务器所允许的挂起连接序列的最大长度
///
public void Start(int backlog)
{
if (!IsRunning)
{
IsRunning = true;
_listener.Start(backlog);
_listener.BeginAcceptTcpClient(
new AsyncCallback(HandleTcpClientAccepted), _listener);
}
}
///
/// 停止服务器
///
public void Stop()
{
if (IsRunning)
{
IsRunning = false;
_listener.Stop();
lock (_clients)
{
//关闭所有客户端连接
CloseAllClient();
}
}
}
///
/// 处理客户端连接的函数
///
///
private void HandleTcpClientAccepted(IAsyncResult ar)
{
if (IsRunning)
{
//TcpListener tcpListener = (TcpListener)ar.AsyncState;
TcpClient client = _listener.EndAcceptTcpClient(ar);
byte[] buffer = new byte[client.ReceiveBufferSize];
TCPClientState state
= new TCPClientState(client, buffer);
lock (_clients)
{
_clients.Add(state);
RaiseClientConnected(state);
}
NetworkStream stream = state.NetworkStream;
//开始异步读取数据
stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
_listener.BeginAcceptTcpClient(
new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);
}
}
///
/// 数据接受回调函数
///
///
private void HandleDataReceived(IAsyncResult ar)
{
if (IsRunning)
{
TCPClientState state = (TCPClientState)ar.AsyncState;
NetworkStream stream = state.NetworkStream;
int recv = 0;
try
{
recv = stream.EndRead(ar);
}
catch
{
recv = 0;
}
if (recv == 0)
{
// connection has been closed
lock (_clients)
{
_clients.Remove(state);
//触发客户端连接断开事件
RaiseClientDisconnected(state);
return;
}
}
// received byte and trigger event notification
byte[] buff = new byte[recv];
Buffer.BlockCopy(state.Buffer, 0, buff, 0, recv);
//触发数据收到事件
RaiseDataReceived(state);
// continue listening for tcp datagram packets
stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
}
}
///
/// 发送数据
///
/// 接收数据的客户端会话
/// 数据报文
public void Send(TCPClientState state, byte[] data)
{
RaisePrepareSend(state);
Send(state.TcpClient, data);
}
///
/// 异步发送数据至指定的客户端
///
/// 客户端
/// 报文
public void Send(TcpClient client, byte[] data)
{
if (!IsRunning)
throw new InvalidProgramException("This TCP Scoket server has not been started.");
if (client == null)
throw new ArgumentNullException("client");
if (data == null)
throw new ArgumentNullException("data");
client.GetStream().BeginWrite(data, 0, data.Length, SendDataEnd, client);
}
///
/// 发送数据完成处理函数
///
/// 目标客户端Socket
private void SendDataEnd(IAsyncResult ar)
{
((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
RaiseCompletedSend(null);
}
#endregion
#region 事件
///
/// 与客户端的连接已建立事件
///
public event EventHandler ClientConnected;
///
/// 与客户端的连接已断开事件
///
public event EventHandler ClientDisconnected;
///
/// 触发客户端连接事件
///
///
private void RaiseClientConnected(TCPClientState state)
{
if (ClientConnected != null)
{
ClientConnected(this, new AsyncEventArgs(state));
}
}
///
/// 触发客户端连接断开事件
///
///
private void RaiseClientDisconnected(TCPClientState state)
{
if (ClientDisconnected != null)
{
ClientDisconnected(this, new AsyncEventArgs("连接断开"));
}
}
///
/// 接收到数据事件
///
public event EventHandler DataReceived;
private void RaiseDataReceived(TCPClientState state)
{
if (DataReceived != null)
{
DataReceived(this, new AsyncEventArgs(state));
}
}
///
/// 发送数据前的事件
///
public event EventHandler PrepareSend;
///
/// 触发发送数据前的事件
///
///
private void RaisePrepareSend(TCPClientState state)
{
if (PrepareSend != null)
{
PrepareSend(this, new AsyncEventArgs(state));
}
}
///
/// 数据发送完毕事件
///
public event EventHandler CompletedSend;
///
/// 触发数据发送完毕的事件
///
///
private void RaiseCompletedSend(TCPClientState state)
{
if (CompletedSend != null)
{
CompletedSend(this, new AsyncEventArgs(state));
}
}
///
/// 网络错误事件
///
public event EventHandler NetError;
///
/// 触发网络错误事件
///
///
private void RaiseNetError(TCPClientState state)
{
if (NetError != null)
{
NetError(this, new AsyncEventArgs(state));
}
}
///
/// 异常事件
///
public event EventHandler OtherException;
///
/// 触发异常事件
///
///
private void RaiseOtherException(TCPClientState state, string descrip)
{
if (OtherException != null)
{
OtherException(this, new AsyncEventArgs(descrip, state));
}
}
private void RaiseOtherException(TCPClientState state)
{
RaiseOtherException(state, "");
}
#endregion
#region Close
///
/// 关闭一个与客户端之间的会话
///
/// 需要关闭的客户端会话对象
public void Close(TCPClientState state)
{
if (state != null)
{
state.Close();
_clients.Remove(state);
_clientCount--;
//TODO 触发关闭事件
}
}
///
/// 关闭所有的客户端会话,与所有的客户端连接会断开
///
public void CloseAllClient()
{
foreach (TCPClientState client in _clients)
{
Close(client);
}
_clientCount = 0;
_clients.Clear();
}
#endregion
#region 释放
///
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release
/// both managed and unmanaged resources; false
/// to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
try
{
Stop();
if (_listener != null)
{
_listener = null;
}
}
catch (SocketException)
{
//TODO
RaiseOtherException(null);
}
}
disposed = true;
}
}
#endregion
}
} 客户端处理封装类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
namespace NetFrame.Net.TCP.Listener.Asynchronous
{
public class TCPClientState
{
///
/// 与客户端相关的TcpClient
///
public TcpClient TcpClient { get; private set; }
///
/// 获取缓冲区
///
public byte[] Buffer { get; private set; }
///
/// 获取网络流
///
public NetworkStream NetworkStream
{
get { return TcpClient.GetStream(); }
}
public TCPClientState(TcpClient tcpClient, byte[] buffer)
{
if (tcpClient == null)
throw new ArgumentNullException("tcpClient");
if (buffer == null)
throw new ArgumentNullException("buffer");
this.TcpClient = tcpClient;
this.Buffer = buffer;
}
///
/// 关闭
///
public void Close()
{
//关闭数据的接受和发送
TcpClient.Close();
Buffer = null;
}
}
} 服务器事件参数类
PpcyAI
泡泡次元AI-游戏美术AI创作平台,低门槛上手,高度可控,让你的创意秒速落地
下载
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NetFrame.Net.TCP.Listener.Asynchronous
{
///
/// 异步TcpListener TCP服务器事件参数类
///
public class AsyncEventArgs:EventArgs
{
///
/// 提示信息
///
public string _msg;
///
/// 客户端状态封装类
///
public TCPClientState _state;
///
/// 是否已经处理过了
///
public bool IsHandled { get; set; }
public AsyncEventArgs(string msg)
{
this._msg = msg;
IsHandled = false;
}
public AsyncEventArgs(TCPClientState state)
{
this._state = state;
IsHandled = false;
}
public AsyncEventArgs(string msg, TCPClientState state)
{
this._msg = msg;
this._state = state;
IsHandled = false;
}
}
} 以上就是C#网络编程系列文章(三)之TcpListener实现异步TCP服务器的内容,更多相关内容请关注PHP中文网(www.php.cn)!