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

基于事件的异步Socket(TCP连接方式)

2010-02-24 17:45 393 查看
代码

//TcpService.cs

using System;
using System.IO;
using System.Text;
using System.Net;
using System.Diagnostics;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace SocketServer
{

/// <summary>
/// 边城浪 QQ:19201576
/// 最后更新:9:57 2007-8-7
/// TCP连接服务器端,接受多客户的TCP连接
/// </summary>
public class TcpService<T>
where T : class, IDataTransmit,new()
{
#region 事件定义

/// <summary>
/// 客户端连接事件
/// </summary>
public event NetEventHandler Connected;
/// <summary>
/// 客户端断开事件
/// </summary>
public event NetEventHandler DisConnect;
#endregion

#region 字段
private readonly int maxsockets; //最大客户连接数
private TcpListener listener; //监听类
private Dictionary<EndPoint, T> session; //保存连接的客户端
#endregion

#region 属性
/// <summary>
/// 当前客户连接数
/// </summary>
public int ConnectCount
{
get { return session.Count; }
}

/// <summary>
/// 与客户连接的所有Socket
/// </summary>
public Dictionary<EndPoint, T> Session
{
get { return session; }
}
#endregion

#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="port">监听的端口号</param>
/// <param name="maxsocket">最大客户连接量</param>
public TcpService(int port, int maxsockets, string ip)
{
if (maxsockets < 1)
{
throw new ArgumentOutOfRangeException("maxsockets", "最大连接数不能小于1");
}
this.maxsockets = maxsockets;
this.listener = new TcpListener(new IPEndPoint(IPAddress.Parse(ip), port));
this.session = new Dictionary<EndPoint, T>();
}

public TcpService(int port)
: this(port, 1000, "0.0.0.0")
{
}
#endregion

#region 公用方法
public void Start(int backlog)
{
listener.Start(backlog);
//监听客户端连接请求
listener.BeginAcceptSocket(clientConnect, listener);
}

/// <summary>
/// 启动服务器程序,开始监听客户端请求
/// </summary>
public void Start()
{
Start(4);
}

private void clientConnect(IAsyncResult ar)
{
TcpListener listener = (TcpListener)ar.AsyncState;
//接受客户的连接,得连接Socket
Socket client = listener.EndAcceptSocket(ar);
client.IOControl(IOControlCode.KeepAliveValues, Keepalive(0,60000,5000), null);

T work = new T();
work.TcpSocket = client;
work.DisConnected += new NetEventHandler(work_DisConnect);

EndPoint socketPoint = client.RemoteEndPoint;
if (session.ContainsKey(socketPoint))
{
session[socketPoint] = work;
}
else
{
session.Add(socketPoint, work);
}

if (ConnectCount < maxsockets)
{
//继续监听客户端连接请求
IAsyncResult iar = listener.BeginAcceptSocket(clientConnect, listener);
}
else
{ //达到最大连接客户数,则关闭监听.
listener.Stop();
}

//客户端连接成功事件
NetEventHandler handler = Connected;
if (handler != null)
{
handler(work, new NetEventArgs("接受客户的连接请求"));
}
Debug.WriteLine(socketPoint.ToString() + " is Connection...Num" + ConnectCount);
}

//客户端断开连接
private void work_DisConnect(IDataTransmit work, NetEventArgs e)
{
EndPoint socketPoint = work.RemoteEndPoint;
session.Remove(socketPoint);

//如果已关闭侦听器,则打开,继续监听
if (ConnectCount == maxsockets)
{
listener.Start(2);
IAsyncResult iar = listener.BeginAcceptSocket(clientConnect, listener);
}

//触发客户断开事件
NetEventHandler handler = DisConnect;
if (handler != null)
{
handler(work, e);
}
Debug.WriteLine(socketPoint.ToString() + " is OnDisConnected...Num" + ConnectCount);
}
#endregion

/// <summary>
/// 得到tcp_keepalive结构值
/// </summary>
/// <param name="onoff">是否启用Keep-Alive</param>
/// <param name="keepalivetime">多长时间后开始第一次探测(单位:毫秒)</param>
/// <param name="keepaliveinterval">探测时间间隔(单位:毫秒)</param>
/// <returns></returns>
public static byte[] Keepalive(int onoff, int keepalivetime, int keepaliveinterval)
{
byte[] inOptionValues = new byte[12];
BitConverter.GetBytes(onoff).CopyTo(inOptionValues, 0);
BitConverter.GetBytes(keepalivetime).CopyTo(inOptionValues, 4);
BitConverter.GetBytes(keepaliveinterval).CopyTo(inOptionValues, 8);
return inOptionValues;
}
}

public class TcpService : TcpService<DataTransmit>
{
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="port">监听的端口号</param>
/// <param name="maxsocket">最大客户连接量</param>
public TcpService(int port, int maxsockets, string ip)
: base(port, maxsockets, ip)
{
}
public TcpService(int port)
: base(port, 1000, "0.0.0.0")
{
}
#endregion
}
}

//NetEventArgs.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace SocketServer
{
/// <summary>
/// 网络通讯事件模型委托
/// </summary>
/// <param name="sender"></param>
/// <param name="e">TcpClient</param>
public delegate void NetEventHandler(IDataTransmit sender, NetEventArgs e);

/// <summary>
/// 网络事件参数
/// </summary>
public class NetEventArgs : EventArgs
{
private object eventArg;

public NetEventArgs(object EventArg)
{
eventArg = EventArg;
}
public object EventArg
{
get { return eventArg; }
set { eventArg = value; }
}

public override string ToString()
{
if (eventArg != null)
{
return eventArg.ToString();
}
else
{
return string.Empty;
}
}
}
}

IDataTransmit.cs

using System;
namespace SocketServer
{
public interface IDataTransmit
{
bool Connected { get; }
/// <summary>
/// 连接失败事件
/// </summary>
event NetEventHandler ConnectFail;
/// <summary>
/// 连接成功事件
/// </summary>
event NetEventHandler ConnectSucceed;
/// <summary>
/// 断开连接事件
/// </summary>
event NetEventHandler DisConnected;
/// <summary>
/// 接收到数据事件
/// </summary>
event NetEventHandler ReceiveData;
/// <summary>
/// 获取远程终结点
/// </summary>
System.Net.EndPoint RemoteEndPoint { get; }
/// <summary>
/// 发送二进制数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
bool Send(byte[] bin);
/// <summary>
/// 发送文本
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
bool Send(string text);
/// <summary>
/// 开始接收数据
/// </summary>
void Start();
/// <summary>
/// 停止
/// </summary>
void Stop();
/// <summary>
/// Socket对象.
/// </summary>
System.Net.Sockets.Socket TcpSocket { get; set;}
}
}

DataTransmit.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;

namespace SocketServer
{
/// <summary>
/// 辅助传输对象
/// </summary>
public class DataTransmit : IDataTransmit
{
#region 事件定义
/// <summary>
/// 连接成功事件
/// </summary>
public event NetEventHandler ConnectSucceed;
/// <summary>
/// 连接失败事件
/// </summary>
public event NetEventHandler ConnectFail;
/// <summary>
/// 断开连接事件
/// </summary>
public event NetEventHandler DisConnected;
/// <summary>
/// 接收到数据事件
/// </summary>
public event NetEventHandler ReceiveData;
#endregion

#region 字段
private Socket socket; //连接的Socket
private EndPoint iep; //网络终节点,用于标识不同的用户
private byte[] buffer; //接收数据缓存
private SocketError errorCode; //错误代码
public const int BagSize = 8192; //缓存大小
#endregion

#region 属性
public Socket TcpSocket
{
get
{
return socket;
}
set
{
if (value == null)
{
throw new ArgumentNullException("client");
}
this.socket = value;
this.socket.ReceiveBufferSize = BagSize;
this.iep = value.RemoteEndPoint;
}
}
/// <summary>
/// 获取远程终结点
/// </summary>
public EndPoint RemoteEndPoint
{
get { return iep; }
}
/// <summary>
/// Socket是否已连接
/// </summary>
public bool Connected
{
get
{
if (socket == null)
{
return false;
}
else
{
return this.socket.Connected;
}
}
}
/// <summary>
/// Socket错误代码
/// </summary>
public SocketError ErrorCode
{
get { return errorCode; }
set { errorCode = value; }
}
#endregion

#region 构造函数
public DataTransmit()
{
errorCode = SocketError.Success;
buffer = new byte[BagSize];
}

public DataTransmit(string ip, int port)
: this(new IPEndPoint(IPAddress.Parse(ip), port))
{
}

/// <summary>
/// 客户端调用此构造函数
/// </summary>
/// <param name="ipPoint">在连接的服务器端网络地址</param>
public DataTransmit(EndPoint ipEndPoint)
: this()
{
iep = ipEndPoint;
}

/// <summary>
/// 服务器端调用
/// </summary>
/// <param name="client">服务器监听连接得到的Socket对象</param>
public DataTransmit(Socket client)
: this()
{
TcpSocket = client;
}
#endregion

public void Stop()
{
if (socket != null)
{
try
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
}
socket.Close();
}
catch { }
socket = null;
}
}

/// <summary>
/// 开始接收数据
/// </summary>
/// <returns></returns>
public void Start()
{
if (socket != null && socket.Connected)
{
receiveData();
}
else
{
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.socket.ReceiveBufferSize = BagSize;
this.socket.BeginConnect(iep, connectCallback, socket);
}
}

private void connectCallback(IAsyncResult ar)
{
try
{
this.socket.EndConnect(ar);
}
catch (Exception err)
{
OnConnectFail(err);
return;
}
//连接成功,开始接收数据
OnConnectSucceed();
receiveData();
}

private void receiveData()
{
// 调用异步方法 BeginReceive 来告知 socket 如何接收数据
IAsyncResult iar = socket.BeginReceive(buffer, 0, BagSize, SocketFlags.None, out errorCode, receiveCallback, buffer);
if ((errorCode != SocketError.Success) && (errorCode != SocketError.IOPending))
{
OnDisConnected(new SocketException((int)errorCode));
}
}

/// <summary>
/// 接收数据回调函数
/// </summary>
/// <param name="ar"></param>
private void receiveCallback(IAsyncResult ar)
{
//接收到的数据长度.
int receLen = 0;
try
{
receLen = socket.EndReceive(ar, out errorCode);
}
catch (Exception err)
{
OnDisConnected(err);
return;
}
if (errorCode == SocketError.Success)
{
if (receLen > 0)
{
byte[] currentBin = new byte[receLen];
Buffer.BlockCopy(buffer, 0, currentBin, 0, receLen);
OnReceiveData(currentBin);
}
receiveData();
}
else
{
OnDisConnected(new SocketException((int)errorCode));
}
}

public virtual bool Send(string text)
{
byte[] bin = Encoding.Default.GetBytes(text);
return Send(bin);
}

public virtual bool Send(byte[] data)
{
if (Connected)
{
this.socket.BeginSend(data, 0, data.Length, SocketFlags.None, out errorCode, sendCallBack, socket);
if (errorCode == SocketError.Success)
{
return true;
}
}
return false;
}

private void sendCallBack(IAsyncResult ar)
{
this.socket.EndSend(ar, out errorCode);
if (errorCode != SocketError.Success)
{
OnDisConnected(new SocketException((int)errorCode));
}
}

#region 受保护的事件处理方法

protected virtual void OnConnectSucceed()
{
NetEventHandler hander = ConnectSucceed;
if (hander != null)
{
ConnectSucceed(this, new NetEventArgs("成功连接到服务器"));
}
}

protected virtual void OnConnectFail(Exception err)
{
NetEventHandler hander = ConnectFail; //连接服务器失败事件
if (hander != null)
{
ConnectFail(this, new NetEventArgs(err));
}
}

protected virtual void OnDisConnected(Exception err)
{
//Stop();
NetEventHandler hander = DisConnected; //断开连接事件
if (hander != null)
{
hander(this, new NetEventArgs(err));
}
}

protected virtual void OnReceiveData(object bin)
{
NetEventHandler hander = ReceiveData; //接收到消息事件
if (hander != null)
{
hander(this, new NetEventArgs(bin));
}
}
#endregion
}
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yeerh/archive/2006/09/25/1280111.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: