您的位置:首页 > 理论基础 > 计算机网络

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

2017-12-13 10:00 567 查看


原创性声明

本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处



文章系列目录

C#网络编程系列文章(一)之Socket实现异步TCP服务器

C#网络编程系列文章(二)之Socket实现同步TCP服务器

C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

C#网络编程系列文章(五)之Socket实现异步UDP服务器

C#网络编程系列文章(六)之Socket实现同步UDP服务器

C#网络编程系列文章(七)之UdpClient实现异步UDP服务器

C#网络编程系列文章(八)之UdpClient实现同步UDP服务器


本文介绍

TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。 可使用 TcpClient 或 Socket 来连接 TcpListener。 可使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener。 可以将本地
IP 地址指定为 Any,将本地端口号指定为 0(如果希望基础服务提供程序为您分配这些值)。 如果您选择这样做,可在连接套接字后使用 LocalEndpoint 属性来标识已指定的信息。使用 Start 方法,可开始侦听传入的连接请求。 Start 将对传入连接进行排队,直至您调用 Stop 方法或它已经完成 MaxConnections 排队为止。 可使用 AcceptSocket 或 AcceptTcpClient 从传入连接请求队列提取连接。 这两种方法将阻止。 如果要避免阻止,可首先使用 Pending
方法来确定队列中是否有可用的连接请求。

虽然TcpListener已经封装的比较不错了,我们于是就使用它在构造一个比较不错的同步TCP服务器,这里依然和前两章一样,给出服务器中的代码,代码中注释很详细,我也会给出相关的封装类。


TcpListener同步TCP服务器

[csharp] view
plain copy

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net.Sockets;

using System.Net;

using System.Threading;

namespace NetFrame.Net.TCP.Listener.Synchronous

{

/// <summary>

/// TcpListener实现同步TCP服务器

/// </summary>

public class TCPServer

{

#region Fields

/// <summary>

/// 服务器程序允许的最大客户端连接数

/// </summary>

private int _maxClient;

/// <summary>

/// 当前的连接的客户端数

/// </summary>

private int _clientCount;

/// <summary>

/// 服务器使用的异步TcpListener

/// </summary>

private TcpListener _listener;

/// <summary>

/// 客户端会话列表

/// </summary>

private List<TCPClientHandle> _clients;

private bool disposed = false;

#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 构造器

/// <summary>

/// 同步TCP服务器

/// </summary>

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

public TCPServer(int listenPort)

: this(IPAddress.Any, listenPort, 1024)

{

}

/// <summary>

/// 同步TCP服务器

/// </summary>

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

public TCPServer(IPEndPoint localEP)

: this(localEP.Address, localEP.Port, 1024)

{

}

/// <summary>

/// 同步TCP服务器

/// </summary>

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

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

/// <param name="maxClient">最大客户端数量</param>

public TCPServer(IPAddress localIPAddress, int listenPort, int maxClient)

{

this.Address = localIPAddress;

this.Port = listenPort;

this.Encoding = Encoding.Default;

_maxClient = maxClient;

_clients = new List<TCPClientHandle>();

_listener = new TcpListener(new IPEndPoint(this.Address, this.Port));

}

#endregion

#region Method

/// <summary>

/// 启动服务器

/// </summary>

public void Start()

{

if (!IsRunning)

{

IsRunning = true;

_listener.Start();

Thread thread = new Thread(Accept);

thread.Start();

}

}

/// <summary>

/// 开始进行监听

/// </summary>

private void Accept()

{

TCPClientHandle handle;

while (IsRunning)

{

TcpClient client = _listener.AcceptTcpClient();

if (_clientCount >= _maxClient)

{

//TODO 触发事件

}

else

{

handle = new TCPClientHandle(client);

_clientCount++;

_clients.Add(handle);

//TODO 创建一个处理客户端的线程并启动

//使用线程池来操作

new Thread(new ThreadStart(handle.RecevieData)).Start();

}

}

}

/// <summary>

/// 停止服务器

/// </summary>

public void Stop()

{

if (IsRunning)

{

IsRunning = false;

_listener.Stop();

//TODO 关闭对所有客户端的连接

}

}

/// <summary>

/// 发送函数

/// </summary>

public void Send(string msg, TcpClient client)

{

//TODO

}

#endregion

#region 事件

/// <summary>

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

/// </summary>

public event EventHandler<TCPEventArgs> ClientConnected;

/// <summary>

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

/// </summary>

public event EventHandler<TCPEventArgs> ClientDisconnected;

/// <summary>

/// 触发客户端连接事件

/// </summary>

/// <param name="state"></param>

private void RaiseClientConnected(TCPClientHandle handle)

{

if (ClientConnected != null)

{

ClientConnected(this, new TCPEventArgs(handle));

}

}

/// <summary>

/// 触发客户端连接断开事件

/// </summary>

/// <param name="client"></param>

private void RaiseClientDisconnected(Socket client)

{

if (ClientDisconnected != null)

{

ClientDisconnected(this, new TCPEventArgs("连接断开"));

}

}

/// <summary>

/// 接收到数据事件

/// </summary>

public event EventHandler<TCPEventArgs> DataReceived;

private void RaiseDataReceived(TCPClientHandle handle)

{

if (DataReceived != null)

{

DataReceived(this, new TCPEventArgs(handle));

}

}

/// <summary>

/// 数据发送事件

/// </summary>

public event EventHandler<TCPEventArgs> CompletedSend;

/// <summary>

/// 触发数据发送事件

/// </summary>

/// <param name="state"></param>

private void RaiseCompletedSend(TCPClientHandle handle)

{

if (CompletedSend != null)

{

CompletedSend(this, new TCPEventArgs(handle));

}

}

/// <summary>

/// 网络错误事件

/// </summary>

public event EventHandler<TCPEventArgs> NetError;

/// <summary>

/// 触发网络错误事件

/// </summary>

/// <param name="state"></param>

private void RaiseNetError(TCPClientHandle handle)

{

if (NetError != null)

{

NetError(this, new TCPEventArgs(handle));

}

}

/// <summary>

/// 异常事件

/// </summary>

public event EventHandler<TCPEventArgs> OtherException;

/// <summary>

/// 触发异常事件

/// </summary>

/// <param name="state"></param>

private void RaiseOtherException(TCPClientHandle handle, string descrip)

{

if (OtherException != null)

{

OtherException(this, new TCPEventArgs(descrip, handle));

}

}

private void RaiseOtherException(TCPClientHandle handle)

{

RaiseOtherException(handle, "");

}

#endregion

#region Close

/// <summary>

/// 关闭一个与客户端之间的会话

/// </summary>

/// <param name="handle">需要关闭的客户端会话对象</param>

public void Close(TCPClientHandle handle)

{

if (handle != null)

{

_clients.Remove(handle);

handle.Dispose();

_clientCount--;

//TODO 触发关闭事件

}

}

/// <summary>

/// 关闭所有的客户端会话,与所有的客户端连接会断开

/// </summary>

public void CloseAllClient()

{

foreach (TCPClientHandle handle in _clients)

{

Close(handle);

}

_clientCount = 0;

_clients.Clear();

}

#endregion

#region 释放

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

{

//TODO 异常

}

}

disposed = true;

}

}

#endregion

}

}

客户端处理封装类

[csharp] view
plain copy

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net.Sockets;

using System.IO;

namespace NetFrame.Net.TCP.Listener.Synchronous

{

/// <summary>

/// TcpListener实现同步TCP服务器 的客户端连接处理类

/// </summary>

public class TCPClientHandle

{

private TcpClient _tcpclient;

private BinaryReader rs;

private BinaryWriter ws;

/// <summary>

/// 标识是否与客户端相连接

/// </summary>

private bool _is_connect;

public bool IsConnect

{

get { return _is_connect; }

set { _is_connect = value; }

}

/// <summary>

/// 数据接受缓冲区

/// </summary>

private byte[] _recvBuffer;

public TCPClientHandle(TcpClient client)

{

_tcpclient = client;

rs = new BinaryReader(client.GetStream());

ws = new BinaryWriter(client.GetStream());

// NetworkStream ns = tmpTcpClient.GetStream();

// if(ns.CanRead&&ns.CanWrite)

_recvBuffer=new byte[client.ReceiveBufferSize];

}

/// <summary>

/// 接受数据

/// </summary>

public void RecevieData()

{

int len = 0;

while (_is_connect)

{

try

{

len = rs.Read(_recvBuffer, 0, _recvBuffer.Length);

}

catch (Exception)

{

break;

}

if (len == 0)

{

//the client has disconnected from server

break;

}

//TODO 处理收到的数据

}

}

/// <summary>

/// 向客户端发送数据

/// </summary>

/// <param name="msg"></param>

public void SendData(string msg)

{

byte[] data = Encoding.Default.GetBytes(msg);

try

{

ws.Write(data, 0, data.Length);

ws.Flush();

}

catch (Exception)

{

//TODO 处理异常

}

}

#region 事件

//TODO 消息发送事件

//TODO 数据收到事件

//TODO 异常处理事件

#endregion

#region 释放

/// <summary>

/// Performs application-defined tasks associated with freeing,

/// releasing, or resetting unmanaged resources.

/// </summary>

public void Dispose()

{

_is_connect = false;

if (_tcpclient != null)

{

_tcpclient.Close();

_tcpclient = null;

}

GC.SuppressFinalize(this);

}

#endregion

}

}

Tcp服务器事件参数类

[csharp] view
plain copy

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace NetFrame.Net.TCP.Listener.Synchronous

{

/// <summary>

/// 同步TcpListener TCP服务器事件类

/// </summary>

public class TCPEventArgs : EventArgs

{

/// <summary>

/// 提示信息

/// </summary>

public string _msg;

/// <summary>

/// 客户端状态封装类

/// </summary>

public TCPClientHandle _handle;

/// <summary>

/// 是否已经处理过了

/// </summary>

public bool IsHandled { get; set; }

public TCPEventArgs(string msg)

{

this._msg = msg;

IsHandled = false;

}

public TCPEventArgs(TCPClientHandle handle)

{

this._handle = handle;

IsHandled = false;

}

public TCPEventArgs(string msg, TCPClientHandle handle)

{

this._msg = msg;

this._handle = handle;

IsHandled = false;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: