//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
{
///
/// 边城浪 QQ:19201576
/// 最后更新:9:57 2007-8-7
/// TCP连接服务器端,接受多客户的TCP连接
///
public class TcpService
where T : class, IDataTransmit,new()
{
#region 事件定义
///
/// 客户端连接事件
///
public event NetEventHandler Connected;
///
/// 客户端断开事件
///
public event NetEventHandler DisConnect;
#endregion
#region 字段
private readonly int maxsockets; //最大客户连接数
private TcpListener listener; //监听类
private Dictionary
#endregion
#region 属性
///
/// 当前客户连接数
///
public int ConnectCount
{
get { return session.Count; }
}
///
/// 与客户连接的所有Socket
///
public Dictionary
{
get { return session; }
}
#endregion
#region 构造函数
///
/// 构造函数
///
/// 监听的端口号
/// 最大客户连接量
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
}
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);
}
///
/// 启动服务器程序,开始监听客户端请求
///
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
///
/// 得到tcp_keepalive结构值
///
/// 是否启用Keep-Alive
/// 多长时间后开始第一次探测(单位:毫秒)
/// 探测时间间隔(单位:毫秒)
///
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
{
#region 构造函数
///
/// 构造函数
///
/// 监听的端口号
/// 最大客户连接量
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
{
///
/// 网络通讯事件模型委托
///
///
/// TcpClient
public delegate void NetEventHandler(IDataTransmit sender, NetEventArgs e);
///
/// 网络事件参数
///
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; }
///
/// 连接失败事件
///
event NetEventHandler ConnectFail;
///
/// 连接成功事件
///
event NetEventHandler ConnectSucceed;
///
/// 断开连接事件
///
event NetEventHandler DisConnected;
///
/// 接收到数据事件
///
event NetEventHandler ReceiveData;
///
/// 获取远程终结点
///
System.Net.EndPoint RemoteEndPoint { get; }
///
/// 发送二进制数据
///
///
///
bool Send(byte[] bin);
///
/// 发送文本
///
///
///
bool Send(string text);
///
/// 开始接收数据
///
void Start();
///
/// 停止
///
void Stop();
///
/// Socket对象.
///
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
{
///
/// 辅助传输对象
///
public class DataTransmit : IDataTransmit
{
#region 事件定义
///
/// 连接成功事件
///
public event NetEventHandler ConnectSucceed;
///
/// 连接失败事件
///
public event NetEventHandler ConnectFail;
///
/// 断开连接事件
///
public event NetEventHandler DisConnected;
///
/// 接收到数据事件
///
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;
}
}
///
/// 获取远程终结点
///
public EndPoint RemoteEndPoint
{
get { return iep; }
}
///
/// Socket是否已连接
///
public bool Connected
{
get
{
if (socket == null)
{
return false;
}
else
{
return this.socket.Connected;
}
}
}
///
/// Socket错误代码
///
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))
{
}
///
/// 客户端调用此构造函数
///
/// 在连接的服务器端网络地址
public DataTransmit(EndPoint ipEndPoint)
: this()
{
iep = ipEndPoint;
}
///
/// 服务器端调用
///
/// 服务器监听连接得到的Socket对象
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;
}
}
///
/// 开始接收数据
///
///
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));
}
}
///
/// 接收数据回调函数
///
///
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
}
}