📄 tcpsockets.cs
字号:
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Text;
using System.Data;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
using System.Configuration;
namespace Utility
{
/// <summary>
/// 网络通讯事件模型委托
/// </summary>
public delegate void NetEvent(object sender, NetEventArgs e);
public delegate void StateEvent(object sender, StateEventArgs e);
/// <summary>
/// Tcp服务器端
/// </summary>
public class TcpServer
{
#region 字段
private int _maxClients = 1000;
private int _port;
private string _IP = "0.0.0.0";
private Socket svrSock;
#endregion
#region 事件定义
/// <summary>
/// 客户端建立连接事件
/// </summary>
public event NetEvent ClientConn;
public event NetEvent UnLink;
#endregion
#region 构造函数
/// <summary>
/// 鉴于Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时.最好将UDP的数据长度控件在548字节(576-8-20)以内.TCP:576-20-20=536
/// 构造函数,默认IP及容纳能力
/// </summary>
public TcpServer()
{
this._port = int.Parse(ConfigurationManager.AppSettings["port"]);
}
#endregion
#region 公用方法
/// <summary>
/// 启动服务器程序,开始监听客户端请求
/// </summary>
public virtual void Start()
{
svrSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(this._IP), this._port);
svrSock.Bind(iep);
svrSock.Listen(this._maxClients);
svrSock.BeginAccept(new AsyncCallback(AcceptCallback), svrSock);
}
/// <summary>
/// 停止服务器程序,还有问题
/// </summary>
public virtual void Stop()
{
try
{
svrSock.Close();
}
catch (Exception ex)
{
//Console.WriteLine(ex.Message);
}
}
#endregion
#region 受保护的方法
protected virtual void AcceptCallback(IAsyncResult iar)
{
Socket oldserver = (Socket)iar.AsyncState;
Socket client = oldserver.EndAccept(iar);
TcpHelper helper = new TcpHelper(client);
//client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1);
//uint dummy = 0;
//byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
//BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
//BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
//BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
//byte[] OUT = new byte[4];
//int recode = client.IOControl(IOControlCode.KeepAliveValues, inOptionValues, OUT);
//recode = OUT[0] + OUT[1] + OUT[2] + OUT[3];
//if (recode != 0)
//{
// if (this.UnLink != null)
// this.UnLink(this, new NetEventArgs(helper));
// return;
//}
client.BeginReceive(helper.Buffer, 0, helper.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), helper);
if (ClientConn != null)
ClientConn(this, new NetEventArgs(helper));
oldserver.BeginAccept(new AsyncCallback(AcceptCallback), oldserver);
}
protected virtual void ReceiveData(IAsyncResult th)
{
TcpHelper helper = (TcpHelper)th.AsyncState;
Socket server = helper.ClientSocket;
try
{
int bytelong = server.EndReceive(th);
if (bytelong == 0)
{
if (this.UnLink != null)
this.UnLink(this, new NetEventArgs(helper));
helper = null;
return;
}
helper.Receive(bytelong);
server.BeginReceive(helper.Buffer, 0, helper.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), helper);
}
catch (Exception ex)
{
if (this.UnLink != null)
this.UnLink(this, new NetEventArgs(helper));
helper = null;
}
}
#endregion
}
[Serializable]
public class TcpHelper
{
#region 字段
/// <summary>
/// 单包大小
/// </summary>
private const int _bagSize = 2048;
/// <summary>
/// 缓冲器
/// </summary>
private byte[] _buffer;
private Socket _clientSocket;
/// <summary>
/// 最后一次动作的时间
/// </summary>
private DateTime _lastTime;
private Timer _timer;
private string _bak;
#endregion
#region 属性
/// <summary>
/// 缓冲器中数据
/// </summary>
public byte[] Buffer
{
set { this._buffer = value; }
get { return this._buffer; }
}
/// <summary>
/// 连接上来的
/// </summary>
public Socket ClientSocket
{
get { return this._clientSocket; }
}
//单包大小,应用层可以用的数据单包大小
public int BagSize
{
get { return _bagSize/2; }
}
/// <summary>
/// 备用属性
/// </summary>
public string Bak
{
get { return _bak; }
set { _bak = value; }
}
#endregion
#region 事件定义
/// <summary>
/// 接收数据事件
/// </summary>
public event StateEvent ReceiveInfo;
#endregion
#region 构造函数
public TcpHelper(Socket client)
{
this._clientSocket = client;
this._buffer = new byte[4096];
_lastTime = DateTime.Now;
_timer = new Timer(new TimerCallback(this.ping), null, 10000, 10000);
}
private void ping(Object stateInfo)
{
long m = (DateTime.Now.Ticks - _lastTime.Ticks) / 10000;
if (m > 2 * 60 * 1000)
{
_clientSocket.Close();
}
if (m > 60 * 1000)
{
byte[] data = new byte[_bagSize];
data[0] = (byte)DataType.Ping;
this.SendSyn(data);
}
}
#endregion
#region 接收任务
/// <summary>
/// 把垃圾清理掉
/// </summary>
/// <param name="bytelong">真正的大小</param>
public void Receive(int bytelong)
{
byte[] realData = new byte[bytelong];
Array.Copy(this._buffer, realData, bytelong);
_lastTime = DateTime.Now;
if (this.ReceiveInfo != null && realData[0] < 0xF0)
this.ReceiveInfo(this, new StateEventArgs(realData));
}
#endregion
#region 发送任务
/// <summary>
/// 发送字符串,通过异步的方式
/// </summary>
/// <param name="content"></param>
public bool SendAsync(byte[] data)
{
if (!this._clientSocket.Connected) return false;
this._clientSocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendEnd), data);
return true;
}
protected virtual void SendEnd(IAsyncResult iar)
{
try
{
int sent = this._clientSocket.EndSend(iar);
}
catch { }
}
/// <summary>
/// 发送同步字符串
/// </summary>
/// <param name="content">字符串</param>
/// <returns>是否成功</returns>
public bool SendSyn(byte[] data)
{
if (!this._clientSocket.Connected) return false;
this._clientSocket.Send(data, 0, data.Length, SocketFlags.None);
return true;
}
#endregion
public void Dispose()
{
this._bak = null;
this._buffer = null;
if (this._clientSocket != null)
this._clientSocket.Close(1);
this.ReceiveInfo = null;
_timer.Dispose();
_timer = null;
this._clientSocket = null;
}
}
public class NetEventArgs : EventArgs
{
#region 字段
/// <summary>
/// 客户端与服务器之间的会话
/// </summary>
private TcpHelper _client;
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="client">客户端会话</param>
public NetEventArgs(TcpHelper client)
{
if (client == null)
{
throw (new ArgumentNullException());
}
_client = client;
}
#endregion
#region 属性
/// <summary>
/// 获得激发该事件的会话对象
/// </summary>
public TcpHelper Client
{
get { return _client; }
}
#endregion
}
public class StateEventArgs : EventArgs
{
#region 字段
/// <summary>
/// 客户端与服务器之间的会话
/// </summary>
private byte[] _data;
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="client">客户端会话</param>
public StateEventArgs(byte[] data)
{
_data = data;
}
#endregion
#region 属性
/// <summary>
/// 获得激发该事件的会话对象
/// </summary>
public byte[] Data
{
get { return _data; }
}
#endregion
}
/// <summary>
/// 系统自用数据类型,值大于等于0XF0
/// </summary>
public enum DataType
{
/// <summary>
/// SOCKET自用
/// </summary>
SocketUsed = 0xF0,
/// <summary>
/// 服务器端测试连接状态
/// </summary>
Ping = 0xF1,
/// <summary>
/// 建立一个分包发送对象,由SOCKETHELPER组合后返给应用层,这种方式不接受>(BagSize-3)*255的数据包
/// 这是一种轻量级的分包,如果要传文件之类的功能,另行实现
/// </summary>
SendPack = 0xF2,
/// <summary>
/// 表示当前的数据为分包发送数据,byte[1] byte[2] 记录是第几个包,长度为255*255,255为进制,因为这轻量级,所以,最大限制为20*255,大约2.7MB
/// </summary>
SendPark = 0xF3,
/// <summary>
/// 建立接收分包
/// </summary>
ReceivePack = 0xF4,
/// <summary>
/// 每一个分包
/// </summary>
ReceivePark = 0xF5
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -