zoukankan      html  css  js  c++  java
  • 基于事件的异步Socket(TCP连接方式)

    代码
    //TcpService.cs

    using System;
    using System.IO;
    using System.Text;
    using System.Net;
    using System.Diagnostics;
    using System.Net.Sockets;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    namespace SocketServer
    {

        
    /// <summary>
        
    /// 边城浪  QQ:19201576
        
    /// 最后更新:9:57 2007-8-7
        
    /// TCP连接服务器端,接受多客户的TCP连接
        
    /// </summary>
        public class TcpService<T>
             
    where T : class, IDataTransmit,new()
        {
            
    #region 事件定义

            
    /// <summary>
            
    /// 客户端连接事件
            
    /// </summary>
            public event NetEventHandler Connected;
            
    /// <summary>
            
    /// 客户端断开事件
            
    /// </summary>
            public event NetEventHandler DisConnect;
            
    #endregion

            
    #region 字段
            
    private readonly int maxsockets;            //最大客户连接数
            private TcpListener listener;               //监听类
            private Dictionary<EndPoint, T> session;    //保存连接的客户端
            #endregion

            
    #region 属性
            
    /// <summary>
            
    /// 当前客户连接数
            
    /// </summary>
            public int ConnectCount
            {
                
    get { return session.Count; }
            }

            
    /// <summary>
            
    /// 与客户连接的所有Socket
            
    /// </summary>
            public Dictionary<EndPoint, T> Session
            {
                
    get { return session; }
            }
            
    #endregion

            
    #region 构造函数
            
    /// <summary> 
            
    /// 构造函数
            
    /// </summary> 
            
    /// <param name="port">监听的端口号</param> 
            
    /// <param name="maxsocket">最大客户连接量</param> 
            public TcpService(int port, int maxsockets, string ip)
            {
                
    if (maxsockets < 1)
                {
                    
    throw new ArgumentOutOfRangeException("maxsockets""最大连接数不能小于1");
                }
                
    this.maxsockets = maxsockets;
                
    this.listener = new TcpListener(new IPEndPoint(IPAddress.Parse(ip), port));
                
    this.session = new Dictionary<EndPoint, T>();
            }

            
    public TcpService(int port)
                : 
    this(port, 1000"0.0.0.0")
            {
            }
            
    #endregion

            
    #region 公用方法
            
    public void Start(int backlog)
            {
                listener.Start(backlog);
                
    //监听客户端连接请求 
                listener.BeginAcceptSocket(clientConnect, listener);
            }

            
    /// <summary> 
            
    /// 启动服务器程序,开始监听客户端请求
            
    /// </summary> 
            public void Start()
            {
                Start(
    4);
            }

            
    private void clientConnect(IAsyncResult ar)
            {
                TcpListener listener 
    = (TcpListener)ar.AsyncState;
                
    //接受客户的连接,得连接Socket
                Socket client = listener.EndAcceptSocket(ar);
                client.IOControl(IOControlCode.KeepAliveValues, Keepalive(
    0,60000,5000), null);

                T work 
    = new T();
                work.TcpSocket 
    = client;
                work.DisConnected 
    += new NetEventHandler(work_DisConnect);

                EndPoint socketPoint 
    = client.RemoteEndPoint;
                
    if (session.ContainsKey(socketPoint))
                {
                    session[socketPoint] 
    = work;
                }
                
    else
                {
                    session.Add(socketPoint, work);
                }

                
    if (ConnectCount < maxsockets)
                {
                    
    //继续监听客户端连接请求 
                    IAsyncResult iar = listener.BeginAcceptSocket(clientConnect, listener);
                }
                
    else
                {   
    //达到最大连接客户数,则关闭监听.
                    listener.Stop();
                }

                
    //客户端连接成功事件
                NetEventHandler handler = Connected;
                
    if (handler != null)
                {
                    handler(work, 
    new NetEventArgs("接受客户的连接请求"));
                }
                Debug.WriteLine(socketPoint.ToString() 
    + " is Connection...Num" + ConnectCount);
            }

            
    //客户端断开连接
            private void work_DisConnect(IDataTransmit work, NetEventArgs e)
            {
                EndPoint socketPoint 
    = work.RemoteEndPoint;
                session.Remove(socketPoint);

                
    //如果已关闭侦听器,则打开,继续监听
                if (ConnectCount == maxsockets)
                {
                    listener.Start(
    2);
                    IAsyncResult iar 
    =  listener.BeginAcceptSocket(clientConnect, listener);
                }

                
    //触发客户断开事件
                NetEventHandler handler = DisConnect;
                
    if (handler != null)
                {
                    handler(work, e);
                }           
                Debug.WriteLine(socketPoint.ToString() 
    + " is OnDisConnected...Num" + ConnectCount);
            }
            
    #endregion
            
            
    /// <summary>
            
    ///  得到tcp_keepalive结构值
            
    /// </summary>
            
    /// <param name="onoff">是否启用Keep-Alive</param>
            
    /// <param name="keepalivetime">多长时间后开始第一次探测(单位:毫秒)</param>
            
    /// <param name="keepaliveinterval">探测时间间隔(单位:毫秒)</param>
            
    /// <returns></returns>
            public static byte[] Keepalive(int onoff, int keepalivetime, int keepaliveinterval)
            {
                
    byte[] inOptionValues = new byte[12];
                BitConverter.GetBytes(onoff).CopyTo(inOptionValues, 
    0);
                BitConverter.GetBytes(keepalivetime).CopyTo(inOptionValues, 
    4);
                BitConverter.GetBytes(keepaliveinterval).CopyTo(inOptionValues, 
    8);
                
    return inOptionValues;
            }
        }

        
    public class TcpService : TcpService<DataTransmit>
        {
            
    #region 构造函数
            
    /// <summary> 
            
    /// 构造函数
            
    /// </summary> 
            
    /// <param name="port">监听的端口号</param> 
            
    /// <param name="maxsocket">最大客户连接量</param> 
            public TcpService(int port, int maxsockets, string ip)
                : 
    base(port, maxsockets, ip)
            {
            }
            
    public TcpService(int port)
                : 
    base(port, 1000"0.0.0.0")
            {
            }
            
    #endregion
        }
    }

    //NetEventArgs.cs

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace SocketServer
    {
        
    /// <summary>
        
    /// 网络通讯事件模型委托
        
    /// </summary>
        
    /// <param name="sender"></param>
        
    /// <param name="e">TcpClient</param>
        public delegate void NetEventHandler(IDataTransmit sender, NetEventArgs e);

        
    /// <summary>
        
    /// 网络事件参数
        
    /// </summary>
        public class NetEventArgs : EventArgs
        {
            
    private object eventArg;

            
    public NetEventArgs(object EventArg)
            {
                eventArg 
    = EventArg;
            }
            
    public object EventArg
            {
                
    get { return eventArg; }
                
    set { eventArg = value; }
            }

            
    public override string ToString()
            {
                
    if (eventArg != null)
                {
                    
    return eventArg.ToString();
                }
                
    else
                {
                    
    return string.Empty;
                }
            }
        }
    }


    IDataTransmit.cs

    using System;
    namespace SocketServer
    {
        
    public interface IDataTransmit
        {
            
    bool Connected { get; }
            
    /// <summary>
            
    /// 连接失败事件
            
    /// </summary>
            event NetEventHandler ConnectFail;
            
    /// <summary>
            
    /// 连接成功事件
            
    /// </summary>
            event NetEventHandler ConnectSucceed;
            
    /// <summary>
            
    /// 断开连接事件
            
    /// </summary>
            event NetEventHandler DisConnected;
            
    /// <summary>
            
    /// 接收到数据事件
            
    /// </summary>
            event NetEventHandler ReceiveData;
            
    /// <summary>
            
    /// 获取远程终结点
            
    /// </summary>
            System.Net.EndPoint RemoteEndPoint { get; }
            
    /// <summary>
            
    /// 发送二进制数据
            
    /// </summary>
            
    /// <param name="data"></param>
            
    /// <returns></returns>
            bool Send(byte[] bin);
            
    /// <summary>
            
    /// 发送文本
            
    /// </summary>
            
    /// <param name="text"></param>
            
    /// <returns></returns>
            bool Send(string text);
            
    /// <summary>
            
    /// 开始接收数据
            
    /// </summary>
            void Start();
            
    /// <summary>
            
    /// 停止
            
    /// </summary>
            void Stop();
            
    /// <summary>
            
    /// Socket对象.
            
    /// </summary>
            System.Net.Sockets.Socket TcpSocket { getset;}
        }
    }


    DataTransmit.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Diagnostics;
    using System.Threading;

    namespace SocketServer
    {
        
    /// <summary>
        
    /// 辅助传输对象
        
    /// </summary>
        public class DataTransmit : IDataTransmit
        {
            
    #region 事件定义
            
    /// <summary>
            
    /// 连接成功事件
            
    /// </summary>
            public event NetEventHandler ConnectSucceed;
            
    /// <summary>
            
    /// 连接失败事件
            
    /// </summary>
            public event NetEventHandler ConnectFail;
            
    /// <summary>
            
    /// 断开连接事件
            
    /// </summary>
            public event NetEventHandler DisConnected;
            
    /// <summary>
            
    /// 接收到数据事件
            
    /// </summary>
            public event NetEventHandler ReceiveData;       
            
    #endregion

            
    #region 字段
            
    private Socket socket;                  //连接的Socket
            private EndPoint iep;                   //网络终节点,用于标识不同的用户
            private byte[] buffer;                  //接收数据缓存
            private SocketError errorCode;          //错误代码
            public const int BagSize = 8192;        //缓存大小
            #endregion

            
    #region 属性
            
    public Socket TcpSocket
            {
                
    get
                {
                    
    return socket;
                }
                
    set
                {
                    
    if (value == null)
                    {
                        
    throw new ArgumentNullException("client");
                    }
                    
    this.socket = value;
                    
    this.socket.ReceiveBufferSize = BagSize;
                    
    this.iep = value.RemoteEndPoint;
                }
            }
            
    /// <summary>
            
    /// 获取远程终结点
            
    /// </summary>
            public EndPoint RemoteEndPoint
            {
                
    get { return iep; }
            }
            
    /// <summary>
            
    /// Socket是否已连接
            
    /// </summary>
            public bool Connected
            {
                
    get
                {
                    
    if (socket == null)
                    {
                        
    return false;
                    }
                    
    else
                    {
                        
    return this.socket.Connected;
                    }
                }
            }
            
    /// <summary>
            
    /// Socket错误代码
            
    /// </summary>
            public SocketError ErrorCode
            {
                
    get { return errorCode; }
                
    set { errorCode = value; }
            }
            
    #endregion

            
    #region 构造函数
            
    public DataTransmit()
            {
                errorCode 
    = SocketError.Success;
                buffer 
    = new byte[BagSize];
            }

            
    public DataTransmit(string ip, int port)
                : 
    this(new IPEndPoint(IPAddress.Parse(ip), port))
            {
            }

            
    /// <summary>
            
    /// 客户端调用此构造函数
            
    /// </summary>
            
    /// <param name="ipPoint">在连接的服务器端网络地址</param>
            public DataTransmit(EndPoint ipEndPoint)
                : 
    this()
            {
                iep 
    = ipEndPoint;
            }

            
    /// <summary>
            
    /// 服务器端调用
            
    /// </summary>
            
    /// <param name="client">服务器监听连接得到的Socket对象</param>
            public DataTransmit(Socket client)
                : 
    this()
            {
                TcpSocket 
    = client;
            }
            
    #endregion

            
    public void Stop()
            {
                
    if (socket != null)
                {
                    
    try
                    {
                        
    if (socket.Connected)
                        {
                            socket.Shutdown(SocketShutdown.Both);                        
                        }
                        socket.Close();
                    }
                    
    catch { }
                    socket 
    = null;
                }
            }

            
    /// <summary>
            
    /// 开始接收数据
            
    /// </summary>
            
    /// <returns></returns>
            public void Start()
            {
                
    if (socket != null && socket.Connected)
                {
                    receiveData();
                }
                
    else
                {
                    
    this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    
    this.socket.ReceiveBufferSize = BagSize;
                    
    this.socket.BeginConnect(iep, connectCallback, socket);
                }
            }

            
    private void connectCallback(IAsyncResult ar)
            {
                
    try
                {
                    
    this.socket.EndConnect(ar);
                }
                
    catch (Exception err)
                {
                    OnConnectFail(err);
                    
    return;
                }
                
    //连接成功,开始接收数据
                OnConnectSucceed();
                receiveData();
            }

            
    private void receiveData()
            {
                
    // 调用异步方法 BeginReceive 来告知 socket 如何接收数据
                IAsyncResult iar = socket.BeginReceive(buffer, 0, BagSize, SocketFlags.None, out errorCode, receiveCallback, buffer);
                
    if ((errorCode != SocketError.Success) && (errorCode != SocketError.IOPending))
                {
                    OnDisConnected(
    new SocketException((int)errorCode));
                }
            }

            
    /// <summary>
            
    /// 接收数据回调函数
            
    /// </summary>
            
    /// <param name="ar"></param>
            private void receiveCallback(IAsyncResult ar)
            {
                
    //接收到的数据长度.
                int receLen = 0;
                
    try
                {
                    receLen 
    = socket.EndReceive(ar, out errorCode);
                }
                
    catch (Exception err)
                {
                    OnDisConnected(err);
                    
    return;
                }
                
    if (errorCode == SocketError.Success)
                {
                    
    if (receLen > 0)
                    {
                        
    byte[] currentBin = new byte[receLen];
                        Buffer.BlockCopy(buffer, 
    0, currentBin, 0, receLen);
                        OnReceiveData(currentBin);
                    }
                    receiveData();
                }
                
    else
                {
                    OnDisConnected(
    new SocketException((int)errorCode));
                }
            }

            
    public virtual bool Send(string text)
            {
                
    byte[] bin = Encoding.Default.GetBytes(text);
                
    return Send(bin);
            }

            
    public virtual bool Send(byte[] data)
            {
                
    if (Connected)
                {
                    
    this.socket.BeginSend(data, 0, data.Length, SocketFlags.None, out errorCode, sendCallBack, socket);
                    
    if (errorCode == SocketError.Success)
                    {
                        
    return true;
                    }
                }
                
    return false;
            }

            
    private void sendCallBack(IAsyncResult ar)
            {
                
    this.socket.EndSend(ar, out errorCode);
                
    if (errorCode != SocketError.Success)
                {
                    OnDisConnected(
    new SocketException((int)errorCode));
                }
            }

            
    #region 受保护的事件处理方法

            
    protected virtual void OnConnectSucceed()
            {
                NetEventHandler hander 
    = ConnectSucceed;
                
    if (hander != null)
                {
                    ConnectSucceed(
    thisnew NetEventArgs("成功连接到服务器"));
                }
            }

            
    protected virtual void OnConnectFail(Exception err)
            {
                NetEventHandler hander 
    = ConnectFail;   //连接服务器失败事件
                if (hander != null)
                {
                    ConnectFail(
    thisnew NetEventArgs(err));
                }
            }

            
    protected virtual void OnDisConnected(Exception err)
            {
                
    //Stop();
                NetEventHandler hander = DisConnected;  //断开连接事件
                if (hander != null)
                {
                    hander(
    thisnew NetEventArgs(err));
                }
            }

            
    protected virtual void OnReceiveData(object bin)
            {
                NetEventHandler hander 
    = ReceiveData;   //接收到消息事件
                if (hander != null)
                {
                    hander(
    thisnew NetEventArgs(bin));
                }
            }
            
    #endregion
        }
    }




    本文来自CSDN博客,转载请标明出处:http:
    //blog.csdn.net/yeerh/archive/2006/09/25/1280111.aspx
  • 相关阅读:
    配置Podfile 一个工程内的多个Target
    iOS开发中的测试框架
    iOS 设置button文字过长而显示省略号的解决办法
    iOS界面的绘制和渲染
    iOS单元测试
    iOS消息转发机制
    对runtime的总结:让你会用Runtime
    Xcode的Refactor使用
    工厂设计模式
    iOS中的数据存储
  • 原文地址:https://www.cnblogs.com/bobofsj11/p/1672884.html
Copyright © 2011-2022 走看看