C#异步SOCKET发送帮肋类,支持UDP,TCP

由于采用了池技术,需要指定最大池容量,以保证内存不泄漏.

另外C#中大量创造 SocketAsyncEventArgs会导致内存不能回收,

using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Linq;

    /// <summary>
    /// 用于辅助异步发送Socket的帮肋类
    /// Ver1.2 增加了对 AsyncSendResult 的池管理,原因为发送数据时,占用了过大的内存.
    ///             增加了对不受控制的对像记数功能.
    /// </summary>
    public class AsyncSocketSendHelper
    {

        #region 客户端联接池
        /// <summary>
        /// 接收SAEA池集合
        /// </summary>
        private ConcurrentStack<SocketAsyncEventArgs> ReceiveSocketArgsPool = new ConcurrentStack<SocketAsyncEventArgs>();

        /// <summary>
        /// 初始化接收socketargs对象池
        /// </summary>
        protected void InitReceiveSocketArgsPool()
        {

        }

        /// <summary>
        /// 创建一个接收SAEA对象,设置最大接收字节数
        /// </summary>
        /// <returns></returns>
        protected virtual SocketAsyncEventArgs CreateReceiveSocketArgs()
        {
            SocketAsyncEventArgs e = new SocketAsyncEventArgs();
            e.Completed += IO_SendComleted;
            return e;
        }

        /// <summary>
        /// 租赁一个接收SAEA对象
        /// </summary>
        /// <returns></returns>
        protected virtual SocketAsyncEventArgs RentReveiveSocketArgs()
        {
            SocketAsyncEventArgs e;

            //增加已经发出的对像数据
            System.Threading.Interlocked.Increment(ref ss);

            return ReceiveSocketArgsPool.TryPop(out e) ? e : CreateReceiveSocketArgs();
        }

        private ushort _SocketArgsPoolNumber = 200;
        /// <summary>
        /// SocketAsyncEventArgs 池最大长度限制
        /// </summary>
        public ushort SocketArgsPoolNumber
        {
            get { return _SocketArgsPoolNumber; }
            set { _SocketArgsPoolNumber = value; }
        }
        //设置缓冲区
        private byte[] arr = new byte[1];

        private long ss;
        /// <summary>
        /// 已经创建但是还没有回收的对像个数,如果这个数据超过1000则表示可能有内存泄漏的风险.异步模式下出现
        /// </summary>
        public long OutControlSocketArgsNumber
        {
            get { return ss; }
        }

        /// <summary>
        /// 归还一个接收SAEA参数
        /// </summary>
        /// <param name="e">还池</param>
        protected virtual void GivebackReceiveSocketArgs(SocketAsyncEventArgs e)
        {
            if (e != null)
            {
                //减少已经发出的对像数据
                 System.Threading.Interlocked.Decrement(ref ss);

                e.UserToken = null;
                //最多只保存200个缓冲接收器功能
                if (ReceiveSocketArgsPool.Count > _SocketArgsPoolNumber)
                {
                    //移除事件
                    e.Completed -= IO_SendComleted;
                    e.SetBuffer(arr, 0, arr.Length);
                    e.Dispose();
                    return;
                }
                ReceiveSocketArgsPool.Push(e);
            }
        }

        #endregion

        /// <summary>
        ///UDP  发送数据服务
        /// </summary>
        /// <param name="socket">用于发送的Socket对像</param>
        /// <param name="udpTarget">udp远程终端点目标</param>
        /// <param name="buff">需要发送的数据</param>
        /// <param name="callBack">回调函数参数为:发送结果,目标节点,发送数据</param>
        /// <param name="userToken">用户数据 </param>
        public virtual void SendToAsyncByUDP(Socket socket, byte[] buff, EndPoint udpTarget = null, Action<AsyncSendResult> callBack = null, object userToken = null)
        {
            if (socket == null)
            {
                throw new NullReferenceException();
            }

            if (buff == null)
            {
                throw new NullReferenceException();
            }
            if (udpTarget == null)
            {
                throw new NullReferenceException();
            }
            SocketAsyncEventArgs e = RentReveiveSocketArgs();
            e.RemoteEndPoint = udpTarget;
            //设置发送缓冲区
            e.SetBuffer(buff, 0, buff.Length);
            try
            {
                //用户标识
                var token = new AsyncSendResult
                {
                    Result = false,
                    RemoteEndPoint = udpTarget.ToString(),
                    SendTime = DateTime.Now,
                    SendData = buff,
                    ResultTime = DateTime.Now,
                    CallBakc = callBack,
                    UserToKen = userToken,
                };
                e.UserToken = token;
                //发送数据
                if (!socket.SendToAsync(e))
                {
                    IO_SendComleted(socket, e);
                }
            }
            catch (SocketException)
            {
                //还池
                GivebackReceiveSocketArgs(e);
            }
            catch (ObjectDisposedException)
            {
                //还池
                GivebackReceiveSocketArgs(e);
            }

        }

        /// <summary>
        /// 发送数据服务
        /// </summary>
        /// <param name="socket">用于发送的Socket对像</param>
        /// <param name="buff">需要发送的数据</param>
        /// <param name="callBack">回调函数参数为:发送结果,目标节点,发送数据</param>
        /// <param name="userToken">用户数据 </param>
        /// <returns></returns>
        public virtual void SendToAsync(Socket socket, byte[] buff, Action<AsyncSendResult> callBack = null, object userToken = null)
        {
            if (socket == null)
            {
                throw new NullReferenceException();
            }

            if (buff == null)
            {
                throw new NullReferenceException();
            }

            SocketAsyncEventArgs e = RentReveiveSocketArgs();
            //设置发送缓冲区
            e.SetBuffer(buff, 0, buff.Length);
            try
            {
                //用户标识
                var token = new AsyncSendResult
                {
                    Result = false,
                    RemoteEndPoint = socket.RemoteEndPoint.ToString(),
                    SendTime = DateTime.Now,
                    SendData = buff,
                    ResultTime = DateTime.Now,
                    CallBakc = callBack,
                    UserToKen = userToken,
                };
                e.UserToken = token;
                //发送数据
                if (!socket.SendAsync(e))
                {
                    IO_SendComleted(socket, e);
                }
            }
            catch (SocketException)
            {
                //还池
                GivebackReceiveSocketArgs(e);
            }
            catch (ObjectDisposedException)
            {
                //还池
                GivebackReceiveSocketArgs(e);
            }
        }

        /// <summary>
        /// 发送数据后的完成功能
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void IO_SendComleted(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                if (e.UserToken != null)
                {
                    AsyncSendResult token = e.UserToken as AsyncSendResult;
                    if (token != null)
                    {
                        //设置结果时间
                        token.ResultTime = DateTime.Now;

                        //发送数据OK
                        if (e.SocketError == SocketError.Success)
                        {
                            token.Result = true;
                            if (token.CallBakc != null)
                            {
                                token.CallBakc(token);
                            }

                        }
                        else
                        {
                            //发送数据失败
                            token.Result = false;
                            if (token.CallBakc != null)
                            {
                                token.CallBakc(token);
                            }
                        }
                    }
                }
            }
            finally
            {
                //还池
                GivebackReceiveSocketArgs(e);
            }
        }

    }

    /// <summary>
    /// 异步发送结果
    /// </summary>
    public class AsyncSendResult
    {
        /// <summary>
        /// 结果
        /// </summary>
        public bool Result { get; set; }

        /// <summary>
        /// 目标节点
        /// </summary>
        public string RemoteEndPoint { get; set; }

        /// <summary>
        /// 发送数据
        /// </summary>
        public byte[] SendData { get; set; }

        /// <summary>
        /// 发送时间
        /// </summary>
        public DateTime SendTime { get; set; }

        /// <summary>
        /// 结果返回时间
        /// </summary>
        public DateTime ResultTime { get; set; }

        /// <summary>
        /// 获取或设置与此操作关联的用户或应用程序对象。
        /// </summary>
        public object UserToKen { get; set; }

        /// <summary>
        /// 用于回调的委托
        /// </summary>
        internal Action<AsyncSendResult> CallBakc { get; set; }
    }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-30 01:06:30

C#异步SOCKET发送帮肋类,支持UDP,TCP的相关文章

python异步socket编程之二

三.异步client与异步server的通信 1. 服务端代码 pythone socket的server段,开放三个端口:10000,10001,10002. 例子中是每个server绑定一个端口,测试的时候需要分别开3个shell,分别运行. 这太麻烦了,就分别用三个Thread来运行这些services #!/usr/bin/env python # # -*- coding:utf-8 -*- # File: multithrd_socket_server.py # import opt

高性能异步Socket框架

这是一个L/V(Length/Value)模型的异步Socket框架.L是指发送byte数组的长度,L固定为10个byte,V是指要发送的byte数组.可以用于处理超长的消息,处理完成的响应也按照L/V模型发送,客户端接收可以参考服务端解析过程. eg: 1.第一次收到的byte[]:0 0 0 0 0 0 1 1 1 2 28 30 18 26 88 99 77 那么先取0 0 0 0 0 0 1 1 1 2,得到长度为1112,对后面的byte(从index10以后)进行存储 2.第二次收到

C# 异步Socket

C# 异步Socket (BeginXXXX)服务器代码 前言: 1.最近维护公司的一个旧项目,是Socket通讯的,主要用于接收IPC(客户端)发送上来的抓拍图像,期间要保持通讯,监测数据包并进行处理.但是看之前那人写的代码个人觉得并不是很适合自己,于是就重写了,不过项目暂时弃置了,为了以后能够方便使用,也方便更多像我一样还是渣渣程序员的人,记录一些心得.我还是坚信那句话,分享才能够进步得更快 2.其实在做之前我对这个东西了解也很少,毕竟以我的认识,在国内C#更多地是用来开发网站,于是也在网上

c#异步Socket Tcp服务器实现

原创性申明 本文作者: 小竹zz  本文地址:http://blog.csdn.net/zhujunxxxxx 转载请注明出处. 介绍 我之前写过一篇IOCP的文章: http://blog.csdn.net/zhujunxxxxx/article/details/43573879 这个比异步socket性能好,因为它复用对象了. 在c#中微软已经提供了TcpListener和TcpClient来实现Tcp的通讯,这部分已经有人写了比较好的异步服务器代码 http://www.cnblogs.c

C#异步数据接收串口操作类

C#异步数据接收串口操作类 使用C#调用传统32位API实现串口操作,整个结构特别的简单.接收数据只需要定义数据接收事件即可. 上传源代码我不会,需要源代码的请与我([email protected])联系.你也可以教我怎么上传源代码. using System; using System.Runtime.InteropServices; /// <summary> /// (C)2003-2005 C2217 Studio  保留所有权利 /// /// 文件名称:     IbmsSeri

Windows 8 Metro 关于StreamSocket与原异步Socket

前一篇 <Windows 8 Metro 关于 StreamSocket MSDN示例阅读>我们基本懂得如何通过StreamSocket 做监听.连接.发送接收数据. 同时前一篇留下的几个疑问,我们在这里进行实验和解答. 在“原有的异步Socket”连接方式与现在WIN8 Metro App 的StreamSocket 如何通信呢? 首先解释下这里说的“原有的异步Socket” 是什么. 在await/async 关键字出现前,我们的Socket异步是依靠System.Net 以及 Syste

项目笔记---C#异步Socket示例

概要 在C#领域或者说.net通信领域中有着众多的解决方案,WCF,HttpRequest,WebAPI,Remoting,socket等技术.这些技术都有着自己擅长的领域,或者被合并或者仍然应用于某些场合.本文主要介绍Socket通讯,因其有着跨平台.跨语言.高性能等优势,适合某些情况的应用以及性能优越的解决方案. 本文是基于一个小项目中的应用,使用了异步方式的Socket通讯,性能上达到多客户端多点通讯,大文件(M-G级别)的文件传输,异步长连接上的性能优势,但此项目也有些不足:未进行大量的

Unity3D中简单的C#异步Socket实现

Unity3D中简单的C#异步Socket实现 简单的异步Socket实现..net框架自身提供了很完善的Socket底层.笔者在做Unity3D小东西的时候需要使用到Socket网络通信.于是决定自己研究研究. 经过不懈努力..O(∩_∩)O哈哈~..自我夸奖一下.终于搞定了.SimpleSocket.cs 由于笔者本身并不是专业的C#程序员.O(∩_∩)O哈哈~.大神就可以直接忽视这篇文章了.顾名思义.哈哈简单的Socket.给那些没接触的盆友参考借鉴下吧.服务社会了 注释一: 本例在编码上

ZeroMQ接口函数之 :zmq_msg_send – 从一个socket发送一个消息帧

ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_msg_send zmq_msg_send(3) ØMQ Manual - ØMQ/3.2.5 Name zmq_msg_send – 从一个socket发送一个消息帧 Synopsis int zmq_msg_send (zmq_msg_t *msg, void *socket, int flags); Description zmq_msg_send函数和zmq_sendmsg(3)函数是完全相同的,只是z