• C#


    Socket类

    初始化

    public socket (AddressFamily addressFamily,SocketType sockettype,ProtocolType protocolType)
    public void Bind(EndPoint localEP);  // 绑定端口 
    public void Listen(int backlog);  // 监听,设置最大连接数
    public bool IsBound { get; } // 端口是否绑定成功
    public AddressFamily AddressFamily { get; }
    public SocketType SocketType { get; }
    public ProtocolType ProtocolType { get; }
    public EndPoint LocalEndPoint { get; }
    public EndPoint RemoteEndPoint{ get; }
    

    (1)AddressFamily:socket解析地址的寻址方案(地址族)

    • InterNetwork:IPV4地址;
    • InterNetworkV6:IPV6地址;

    (2)SocketType:socket类型

    • Raw:支持基础传输协议访问;
    • Stream:流式Socket,支持可靠、双向、面向连接的字节数据流;
    • Dgram:数据包式Socket,支持数据报,不可靠消息、面向无连接的数据报;
    • Rdm:支持无连接、面向消息、以可靠方式发送的消息,保留数据中的消息边界,消息会依次到达,不会重复;

    (3)ProtocolType:socket支持的网络协议

    • IP:网际协议;
    • TCP:传输控制协议;
    • UDP:用户数据报协议;

    (4)监听连接:3种方式监听客户端连接

    • Accept()方式:同步阻塞;
    • AcceptAsync()方式:异步;
    • BeginAccept()方式:异步; 

    关闭回收

    public void Shutdown(SocketShutdown how);  // 禁用某Socket上的发送和接收
    public void Close();  // 关闭Socket连接并释放所有关联的资源
    public void Dispose();  // 释放由Socket类的当前实例占用的所有资源
    protected virtual void Dispose(bool disposing);  // 释放由Socket使用的非托管资源和托管资源
    

    (1)Shutdown()

    若使用面向连接的Socket,须先调用Shutdown方法,才能关闭Socket。确保关闭已连接的Socket前,已发送和接收该Socket上的所有数据,调用Close方法释放与Socket关联的所有托管资源和非托管资源。关闭Socket后不要尝试重用它。 

    (2)Close()

    (3)Socket对象的优雅关闭 

    状态信息

    public bool Blocking { get; set; } // 指示Socket是否处于阻止模式
    public bool Connected { get; } // 指示Socket上次Send/Receive操作时连接到远程主机时的状态
    public int Available { get; } // 获取已经从网络接收且可供读取的数据量
    public bool Poll(int microSeconds, SelectMode mode);  // 确定Socket的状态
    public static void Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds); // 确定1个或多个Socket的状态
    

    (1)Connected

    (2)Available 

    (3)Poll()

    (4)Select()

    检测客户端Socket是否已关闭(可读数据检测)

     a.利用Available属性 + Receive()方法

    •  客户端直接关闭,Available属性返回0,但不会引发异常;
    •  客户端通过shutdown-close关闭Socket,Available属性返回0,但不会引发异常;

     b.利用poll()方法 + Receive()方法

    •  客户端直接关闭,poll()方法直接引发异常;
    •  客户端通过shutdown-close关闭Socket,Receive()立即返回0而不会阻塞(若Socket连接正常,Receive()会阻塞);  

    同步方式

    public void Connect(EndPoint remoteEP);  // 建立与远程主机的连接
    public void Disconnect(bool reuseSocket);  // 关闭Socket连接并允许重用Socket 
    public Socket Accept();  // 为新建连接创建新的Socket
    public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode);  // 将数据发送到连接的Socket的发送缓冲区
    public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode);  // 从绑定的Socket接收数据存入接收缓冲区
    

    (1)Accept()

    (2)Send()

    (3)Receive()

    在面向连接的Socket中,如果没有可读取的数据,Receive方法将一直处于阻止状态、直到数据可用(除非使用Socket.ReceiveTimeout设置了超时值),此时Receive方法会读取所有可用的数据,直到达到缓冲区的大小为止。如果远程主机使用Shutdown方法关闭了Socket连接,并且所有可用数据均已收到,则Receive方法将立即完成并返回0字节。  

     APM:Begin/End

    public IAsyncResult BeginAccept(AsyncCallback callback, object state); // 开始一个异步操作接受一个传入的连接尝试
    public Socket EndAccept(IAsyncResult asyncResult); // 异步接受传入的连接尝试,创建新的Socket与远程主机通信
    public IAsyncResult BeginConnect(Xxx, AsyncCallback callback, object state); // 开始一个对远程主机连接的异步请求
    public void EndConnect(IAsyncResult asyncResult); // 结束挂起的异步连接请求
    public IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback callback, object state); // 开始异步请求从远程终结点断开连接
    public void EndDisconnect(IAsyncResult asyncResult); // 结束挂起的异步断开连接请求
    public IAsyncResult BeginSend(Xxx, AsyncCallback callback, object state); // 开始将数据异步发送到连接的Socket
    public int EndSend(IAsyncResult asyncResult); // 结束挂起的异步发送
    public IAsyncResult BeginReceive(Xxx, AsyncCallback callback, object state); // 开始从连接的Socket中异步接收数据
    public int EndReceive(IAsyncResult asyncResult);  // 结束挂起的异步接收
    

    TAP

    监听

    IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _port);
    Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// Create a TCP/IP socket.
    try {
    	listener.Bind(localEndPoint);// Bind the socket to the local endpoint and listen for incoming connections.
    	listener.Listen(10); //最大监听数
    	while (true) {
    		// Set the event to nonsignaled state.
    		allDone.Reset();
    
    		// Start an asynchronous socket to listen for connections. 
    		Console.WriteLine("Waiting for a connection");
    		StateObject state = new StateObject();
    		listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
    			 
    		// Wait until a connection is made before continuing.
    		allDone.WaitOne();
    	}
    } catch (Exception e) { }
    

    数据接收流向: StartListening --> AcceptCallback --> ReceiveCallback --> 主处理 

    发送流向: Send --> SendCallback -->发送完成 

    参考1参考2 

    APM模式、TAP模式虽然解决了Socket的并发问题,但在大并发下会有较大性能问题,生产IAsyncResult等对象导致垃圾对象创建与回收。提供一个过度方法 BufferManager 仅供参考:socket发送接收缓冲区工具类

    微软从.Net3.5提供了高性能异步Socket实现类

    SAEA:SocketAsyncEventArgs类

    表示异步套接字操作,主要用于高性能网络服务器应用程序,避免在异步套接字I/O量非常大时发生重复的对象分配和同步。

    public bool ConnectAsync(SocketAsyncEventArgs e);  // 开始一个连接远程主机的异步请求
    public static void CancelConnectAsync(SocketAsyncEventArgs e);  // 取消一个对远程主机连接的异步请求
    public bool DisconnectAsync(SocketAsyncEventArgs e);  // 开始异步请求从远程终结点断开连接
    public bool AcceptAsync(SocketAsyncEventArgs e);  // 开始一个异步操作接受一个传入的连接尝试
    public bool SendAsync(SocketAsyncEventArgs e);  // 将数据异步发送到连接的Socket对象
    public bool ReceiveAsync(SocketAsyncEventArgs e);  // 开始一个异步请求从连接的Socket对象中接收数据
    

    (1)返回值

    • 如果I/O操作挂起,返回true,操作完成时,引发e参数的SocketAsyncEventArgs.Completed事件;
    • 如果I/O操作同步完成,返回false,这种情况下,不会引发e参数的SocketAsyncEventArgs.Completed事件,并且可能在方法调用返回后立即检查作为参数传递的e对象以检索操作的结果;

    使用步骤

    • 分配一个新的SocketAsyncEventArgs上下文对象,或者从应用程序池中获取一个空闲的此类对象
    • 将该上下文对象的属性设置为要执行的操作(eg:完成回调方法、数据缓冲区、缓冲区偏移量以及要传输的最大数据量)
    • 调用适当的异步套接字方法xxxAsync()启动异步操作:
      • 如果方法xxxAsync()返回true,则在回调中查询上下文属性来获取完成状态
      • 如果方法xxxAsync()返回false,则说明操作是同步完成的,可以查询上下文属性来获取操作结果
    • 将该上下文重用于另一个操作:放回应用程序池中,或者丢弃

    实例实战

    参考1参考2

    参考

     

  • 相关阅读:
    双系统卸载linux和装双系统的方法
    linux中使用vim编译C++程序
    存储器管理之页面置换算法
    Python中open文件的各种打开模式
    RAL调用
    分布式系统事务一致性解决方案
    消息队列设计
    nmq消息队列解析
    分布式session的实现
    分布式系统常用思想和技术总结 (入门很清楚)
  • 原文地址:https://www.cnblogs.com/wjcx-sqh/p/6147867.html
Copyright © 2020-2023  润新知