异步套接字实现

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值