TCP 异步套接字,UDP异步套接字封装和使用
1.tcp为有连接的套接字,客户端套接字断开连接的时候服务端会自动断开接受,但服务端断开连接客户端接受线程一直运行,暂没办法解决。
2.tcp套接字可重用,客户端套接字可无限次数的连接和断开,服务端套接字可无限次的监听和停止。
3.tcp服务端和客户端接受,udp接受采用的是类似事件的异步委托,每次接收到的数据都会触发委托。
4.套接字交互数据进行简单的封装,从buffer到实体,从实体到buffer。
5.tcp客户端连接发送,tcp服务端发送,udp发送进行超时封装,事件完成或超时时自动触发委托并返回不同的结果
===SocketHelper文件========
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Xml;
namespace SocketHelper
{
public class SocketHelpr
{
/// <summary>
/// 来自客户端的注册请求
/// </summary>
public static string INVOKEREGISTER = "INVOKEREGISTER";
/// <summary>
/// 来自客户端的会话请求
/// </summary>
public static string INVOKETALK = "INVOKETALK";
/// <summary>
/// 来自服务端的会话验证
/// </summary>
public static string TALKVALIDATE = "TALKVALIDATE";
/// <summary>
/// 来自服务端的更新请求
/// </summary>
public static string UPDATELIST = "UPDATELIST";
/// <summary>
/// 超时工作,当超时发生时返回连接超时
/// </summary>
/// <param name="iTimeOut">超时时间,以毫秒为单位</param>
/// <param name="act">耗时的工作</param>
/// <param name="actTimeOut">当耗时工作完成时或者达到超时时作为回调调用</param>
public static void TimeOutAction(int iTimeOut, Action act, Action<string> actTimeOut)
{
int iCount = 0;
bool bStart = false;
bool bExcute = false;
Thread thread = new Thread((o) =>
{
bStart = true;
try
{
act();
if (bExcute == false)
{
bExcute = true;
actTimeOut("");
}
bStart = false;
}
catch (Exception e)
{
if (bExcute == false)
{
bExcute = true;
actTimeOut(e.Message);
}
bStart = false;
}
});
Thread timer = new Thread((o) =>
{
while (true)
{
Thread.Sleep(100);
iCount++;
if (iCount * 100 >= iTimeOut)
{
if (bStart == true)
{
thread.Abort();
if (bExcute == false)
{
bExcute = true;
actTimeOut("连接超时");
}
return;
}
}
}
});
timer.IsBackground = true;
thread.IsBackground = true;
timer.Start();
thread.Start();
}
/// <summary>
/// 将byte数组转会为实体对象,该实体不支持数组或嵌套对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="buffer"></param>
/// <returns></returns>
public static T GetData<T>(byte[] buffer)
{
return XmlSerialize<T>(Encoding.Default.GetString(buffer));
}
/// <summary>
/// 将实体对象转会为byte数组,该实体不支持数组或嵌套对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tmp"></param>
/// <returns></returns>
public static byte[] GetData<T>(T tmp)
{
return Encoding.Default.GetBytes(XmlSerialize<T>(tmp));
}
/// <summary>
/// 从xml字符串序列化为实体对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml"></param>
/// <returns></returns>
public static T XmlSerialize<T>(string xml)
{
try
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(xml);
T obj = Activator.CreateInstance<T>();
foreach (XmlElement e in xd.DocumentElement.ChildNodes)
{
try
{
var pi = obj.GetType().GetProperty(e.Name);
if (pi != null && pi.GetSetMethod() != null)
pi.SetValue(obj, e.InnerText, null);
}
catch { }
}
return obj;
}
catch (Exception e)
{
return default(T);
}
}
/// <summary>
/// 将简单对象序列化为xml字符串
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string XmlSerialize<T>(T obj)
{
string XmlHead = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><root>";
foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
XmlHead += string.Format("<{0}>{1}</{0}>", pi.Name, pi.GetValue(obj, null));
}
foreach (FieldInfo fi in obj.GetType().GetFields())
{
if (fi.IsPublic == false)
continue;
XmlHead += string.Format("<{0}>{1}</{0}>", fi.Name, fi.GetValue(obj));
}
XmlHead += "</root>";
return XmlHead;
}
}
}
===========TCP异步套接字======================
using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using SocketHelper;
namespace TcpSocket
{
/// <summary>
/// Tcp服务端
/// </summary>
/// <typeparam name="T"></typeparam>
public class TcpSocketServer<T>
{
private IPEndPoint endPoint;
private int timeOut = 5000;
private byte[] buffer = new byte[4096];
private Action<Socket,T> actReceive;
private string ipAdress;
private int iPort;
private void AcceptBack(IAsyncResult ar)
{
if (socketServer == null)
return;
Socket socketClient = null;
try
{
socketClient = socketServer.EndAccept(ar);
}
catch
{
return;
}
if (socketClient == null)
return;
try
{
Array.Clear(buffer, 0, 4096);
socketClient.BeginReceive(buffer, 0, 4096, SocketFlags.None, new AsyncCallback(ReceiveBack), socketClient);
}
catch
{
}
socketServer.BeginAccept(new AsyncCallback(AcceptBack), null);
}
private void ReceiveBack(IAsyncResult ar)
{
var socketClient = ar.AsyncState as Socket;
if (socketClient == null || socketClient.Connected == false)
return;
try
{
socketClient.EndReceive(ar);
}
catch
{
return;
}
var tmp = SocketHelpr.GetData<T>(buffer);
if (tmp == null) return;
actReceive(socketClient, tmp);
try
{
socketClient.BeginReceive(buffer, 0, 4096, SocketFlags.None, new AsyncCallback(ReceiveBack), socketClient);
}
catch
{
}
}
private Socket socketServer;
/// <summary>
/// 创建服务端套接字实体
/// </summary>
/// <param name="IPAdress">监听的IP地址</param>
/// <param name="iPort">监听的端口号</param>
public TcpSocketServer(string IPAdress, int Port)
{
this.ipAdress = IPAdress;
this.iPort = Port;
}
/// <summary>
/// 开启套接字监听
/// </summary>
public void Start()
{
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
endPoint = new IPEndPoint(IPAddress.Parse(this.ipAdress), iPort);
socketServer.Bind(endPoint);
socketServer.Listen(5);
socketServer.BeginAccept(new AsyncCallback(AcceptBack), null);
}
/// <summary>
/// 关闭监听的套接字并释放资源
/// </summary>
public void Stop()
{
try
{
socketServer.Close();
socketServer = null;
}
catch
{
}
}
/// <summary>
/// 设置超时值,主要为发送会话超时
/// </summary>
public int iTimeOut
{
get
{
if (timeOut < 1000 || timeOut > 60000)
return 5000;
else
return timeOut;
}
set
{
this.timeOut = value;
}
}
/// <summary>
/// 客户端会话接入
/// </summary>
/// <typeparam name="T">会话实体类</typeparam>
/// <param name="socketClient">客户端套接字</param>
/// <param name="act"></param>
public void BeginReceive(Action<Socket,T> act)
{
this.actReceive = act;
}
/// <summary>
/// 服务端向客户端发起会话
/// </summary>
/// <param name="tmp"></param>
/// <param name="act"></param>
public void BeginSend(Socket socketClient,T tmp, Action<string> act)
{
SocketHelpr.TimeOutAction(iTimeOut, () => { socketClient.Send(SocketHelpr.GetData<T>(tmp)); }, act);
}
}
/// <summary>
/// Tcp客户端
/// </summary>
/// <typeparam name="T"></typeparam>
public class TcpSoketClient<T>
{
private Action<T> actReceive;
private IPEndPoint endPoint;
private byte[] buffer = new byte[4096];
private int timeOut = 5000;
private string ipAdress;
private int iPort;
private Socket socketClient;
private void ReceiveBack(IAsyncResult ar)
{
try
{
socketClient.EndReceive(ar);
}
catch
{
return;
}
var tmp = SocketHelpr.GetData<T>(buffer);
if (tmp == null)
return;
this.actReceive(tmp);
try
{
Array.Clear(buffer, 0, 4096);
socketClient.BeginReceive(buffer, 0, 4096, SocketFlags.None, new AsyncCallback(ReceiveBack), null);
}
catch (Exception e)
{
if (socketClient != null)
this.DisConnect();
}
}
/// <summary>
/// 客户端套接字构造
/// </summary>
/// <param name="IPAdress">绑定的IP</param>
/// <param name="Port">绑定的端口</param>
public TcpSoketClient(string IPAdress, int Port)
{
this.ipAdress = IPAdress;
this.iPort = Port;
}
/// <summary>
/// 设置超时值,主要为连接服务端和发送会话超时
/// </summary>
public int iTimeOut
{
get
{
if (timeOut < 1000 || timeOut > 60000)
return 5000;
else
return timeOut;
}
set
{
this.timeOut = value;
}
}
/// <summary>
/// 监听当前服务端接入的会话
/// </summary>
/// <param name="act"></param>
public void BeginReceive(Action<T> act)
{
this.actReceive = act;
Array.Clear(buffer, 0, 4096);
socketClient.BeginReceive(buffer, 0, 4096, SocketFlags.None, new AsyncCallback(ReceiveBack), null);
}
/// <summary>
/// 关闭与服务端套接字的会话,释放资源
/// </summary>
public void DisConnect()
{
this.socketClient.Close();
this.socketClient = null;
}
/// <summary>
/// 连接服务端套接字
/// </summary>
/// <param name="act">string为空时表示接入正常,其它情况表示没有接入</param>
public void BeginConnect(Action<string> act)
{
if (socketClient == null)
{
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
endPoint = new IPEndPoint(IPAddress.Parse(this.ipAdress), this.iPort);
}
SocketHelpr.TimeOutAction(iTimeOut, () => { socketClient.Connect(endPoint); }, act);
}
/// <summary>
/// 像服务端发送数据
/// </summary>
/// <param name="tmp"></param>
/// <param name="act"></param>
public void BeginSend(T tmp, Action<string> act)
{
SocketHelpr.TimeOutAction(iTimeOut, () => { socketClient.Send(SocketHelpr.GetData<T>(tmp)); }, act);
}
}
}
======UDP异步套接字==============
using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using SocketHelper;
namespace UdpSocket
{
public class UdpSocket<T>
{
private string ipAdress;
private int iPort;
private Socket socket;
private byte[] buffer = new byte[4096];
private int TimeOut = 5000;
private Action<string, int, T> actReceive;
private EndPoint endPoint;
private void ReceiveBack(IAsyncResult ar)
{
try
{
socket.EndReceiveFrom(ar, ref endPoint);
}
catch
{
return;
}
var tmp = SocketHelper.SocketHelpr.GetData<T>(buffer);
if (tmp == null || endPoint == null)
return;
this.actReceive((endPoint as IPEndPoint).Address.ToString(), (endPoint as IPEndPoint).Port, tmp);
try
{
Array.Clear(buffer, 0, 4096);
socket.BeginReceiveFrom(buffer, 0, 4096, SocketFlags.None, ref endPoint, new AsyncCallback(ReceiveBack), null);
}
catch
{
return;
}
}
/// <summary>
/// Udp套接字实体构造
/// </summary>
/// <param name="IPAdress">ip地址</param>
/// <param name="Port">端口号</param>
public UdpSocket(string IPAdress, int Port)
{
this.ipAdress = IPAdress;
this.iPort = Port;
}
/// <summary>
/// 开启服务
/// </summary>
public void Start()
{
if(socket == null)
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
Array.Clear(buffer, 0, 4096);
endPoint = new IPEndPoint(IPAddress.Parse(ipAdress), iPort);
socket.Bind(endPoint);
socket.BeginReceiveFrom(buffer, 0, 4096, SocketFlags.None, ref endPoint, new AsyncCallback(ReceiveBack), null);
}
/// <summary>
/// 关闭服务
/// </summary>
public void Stop()
{
socket.Close();
socket = null;
}
/// <summary>
/// 设置发送回话超时值
/// </summary>
public int iTimeOut
{
get
{
return TimeOut;
}
set
{
if (value < 1000 || value > 60000)
TimeOut = 5000;
else
TimeOut = value;
}
}
/// <summary>
/// 发送会话
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="IPAdress">目的IP</param>
/// <param name="Port">目的端口号</param>
/// <param name="data">发送的数据</param>
/// <param name="act">发送结果</param>
public void BeginSend(string IPAdress, int Port, T data, Action<string> act)
{
EndPoint point = new IPEndPoint(IPAddress.Parse(IPAdress), Port);
SocketHelper.SocketHelpr.TimeOutAction(TimeOut, () => { socket.SendTo(SocketHelper.SocketHelpr.GetData<T>(data), point); }, act);
}
/// <summary>
/// 接收会话
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="act"></param>
public void BeginReceive(Action<string,int,T> act)
{
this.actReceive = act;
}
}
}