异步套接字实现

来源:互联网 发布:cf出现网络异常 编辑:程序博客网 时间:2024/06/08 06:43

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;        }    }}
0 0
原创粉丝点击