异步套接字实现
来源:互联网 发布: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
- 异步套接字实现
- 异步套接字编程
- VC 异步套接字
- 异步套接字示例
- 异步套接字编程
- 异步套接字
- 异步套接字
- 异步套接字
- 套接字 同步 异步
- 异步套接字
- 异步套接字编程:
- vc异步套接字
- 异步套接字
- 设置异步套接字
- (转51CTO)C#异步套接字实现原理
- DotNet:Socket Server 异步套接字服务端实现
- 深入了解异步套接字
- 深入了解异步套接字
- 69. Sqrt(x)
- nginx在windows下配置反向代理
- Android 线程池 工作调度
- codeforces 614B
- android monkey测试
- 异步套接字实现
- 带大家一步一步的封装一个聊天键盘
- [实战] 用数人云,部署弹性 ELK 集群就五步
- apache多站点配置
- 架构一个后台管理系统的技术所需要的技术
- STL_算法_逆转(reverse,reverse_copy)
- HTML之表单标签
- 【JS学习笔记】JS基础上:数据类型
- 四种常见的 POST 提交数据方式