异步实现Socket Server&Client


异步实现Socket Server&Client
异步实现Socket Server&Client

贴图图片

Introduction

I’ve been working with sockets since 2000, using Delphi 5.0 and some third-party libraries (Synapse). My very first socket application just copied files between many clients and one server. The client app checks a folder to see if files exist, asks the server where to copy the files in the network and, after copying the files, flags the database record indicating that a file has been moved. The server listens to the client connections, and both exchange XML messages indicating the state of each file copy. Synapse is a blocking socket implementation, and I needed a thread pooling mechanism that works like an HTTP server, because I couldn’t keep the connection open (one thread per connection). My solution was to use some IOCP functions to pool the client requests (code) and close the connection after the message exchange was terminated.

Now, using C#, I decided to write a socket server and client library that helps me to only have to think about the message exchange (the process) and let .NET do the hard job. So, I needed the following features:

  • Asynchronous processing
  • Some encryption and compression capabilities
  • Encapsulate the socket, and encrypt the services in the interfaces and separate them from the host implementation

介绍 Introduction

我从2000年就开始使用Delphi5.0套接字编程,并使用一些第3方控件库如(Synapse). 我编写的第一个套接字应用程序是基于一个服务端和多个客户端之间的文件复制. 当开始复制文件时客户端程序需要检查文件存在,如果存在则反馈信息给服务端确认. 复制完成后在数据库对应的记录上打上标记, 标志该文件已经移动到客户端。服务端监听客户连接状态,两端通过交换XML文件来跟踪每个文件的复制情况。Synapse是通过阻塞套接字实现,我需要一个像HTTP服务器线程池的机制,因为我不能保持每个连接线程的Open状态.我的解决方案是在信息交换终止后使用IOCP功能建立客户端请求(代码)和关闭连接池.

注: IOCP全称I/O Completion Port,中文译为I/O完成端口。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。

现在, 我决定用C#开发一个服务端与客户端基于套接字通讯的功能库, 我只关心信息交换相关工作,让.Net去完成那些艰巨的任务。

我需要设计以下功能:
1.异步处理
2.加密及压缩功能
3.在服务端,封装套接字及加密接口中的服务分开实现.

www.csframework.com

Socket Connection



The ISocketConnection is the base interface for the socket connections, and describes all the connection properties and the methods. The ConnectionID property defines a unique connection ID using a GUID string. The CustomData property defines a custom object that can be associated with the connection. The Header property is the socket service header used in each message that is encapsulated in a packet message. Only messages with a defined header will be accepted. The LocalEndPoint and RemoteEndPoint are the socket IP end points used in the connection. SocketHandle is the socket handle given by the OS.

The IClientSocketConnection and IServerSocketConnection inherit the ISocketConnection, and each one has special functions. The IClientSocketConnection can reconnect to the server using the BeginReconnect method, and the IServerSocketConnection can communicate with other connections in the server host using the BeginSendTo and BeginSendToAll methods, and can get the ConnectionId using the GetConnectionById method. Every connection knows the host, the encryption, the compression type, and can send, receive, and disconnect itself from the other part. This interface is used in the ISocketService interface to allow the user to interact with socket connections.


Socket Connection

原始接口IsocketConnection用于套接字连接,定义所有连接属性及方法。ConnectionID属性定义一个GUID连接编号. CustomData属性是一个用于连接传输的自定义对象. Header属性是封装在数据包头部用于套接字服务的信息.(Message:数据包或消息,服务端与客户端传输的内容). 只有定义特殊头部的消息才能被接受。LocalEndPoint和RemoteEndPoint用于记录套接字IP地址. SocketHandle是操作系统分配的句柄(Handle)

IClientSocketConnection和IServerSocketConnection接口继承ISocketConnection接口,它们分别定义特有的功能。IClientSocketConnection接口用BeginReconnect方法重新建立与服务器的连接。IServerSocketConnection接口使用BeginSendTo和BeginSendToAll方法与每一个已建立连接的客户端通讯, 可以通过GetConnectionById方法获取连接(ConnectionId)。每个连接知道主机的位置,加密方式,压缩类型及发送/接收和断线。此接口通过ISocketService接口允许用户之间互相通讯。


 


 

Internally, in the library implementation, all the connection interfaces are created using the base connection implementations: BaseSocketConnection, ClientSocketConnection, and ServerSocketConnection.


剖析类库内部实现,所有连线接口是使用原始接口实现:BaseSocketConnection,ClientSocketConnection和ServerSocketConnection。

Socket Service



The ISocketService describes the connection events. These events are fired by the host, and have a ConnectionEventArgs argument which has an ISocketConnection that identifies the connection. In the OnReceived and OnSent events, a MessageEventArgs is passed, which has the sent or received array of bytes. In the OnDisconnected event, a DisconnectedEventArgs is passed; the Exception property indicates if the disconnection has been caused by an exception.

Here is an example of a ISocketService implementation:


Socket Service

ISocketService接口定义一些连接事件。这些事件由主机引发,事件的ConnectionEventArgs参数记录一个标识连接的ISocketConnection接口。OnReceived 和 OnSent 事件传递一个MessageEventArgs参数,该参数记录传输的字节数组.OnDisconnected事件传递一个DisconnectedEventArgs 参数。Exception属性记录断线后引发的异常。

ISocketService接口实现:


 

public class SimpleEchoService : ISocketService
{
   public void OnConnected(ConnectionEventArgs e)
   {
      //----- Check the host!
      
      if (e.Connection.HostType == HostType.htServer)
      {
         //----- Enqueue receive!
         
         e.Connection.BeginReceive();
      }
      else
      {
         //----- Enqueue send a custom message!
         
         byte[] b =
         GetMessage(e.Connection.SocketHandle.ToInt32());
         e.Connection.BeginSend(b);
      }
   }
   
   public void OnSent(MessageEventArgs e)
   {
      //----- Check the host. In this case both start a receive!
      
      if (e.Connection.HostType == HostType.htServer)
      {
         //----- Enqueue receive!
         
         e.Connection.BeginReceive();
      }
      else
      {
         //----- Enqueue receive!
         
         e.Connection.BeginReceive();
      }
   }
   
   public override void OnReceived(MessageEventArgs e)
   {
      //----- Check the host!
      
      if (e.Connection.HostType == HostType.htServer)
      {
         //----- If server, send the data buffer received!
         
         byte[] b = e.Buffer;
         e.Connection.BeginSend(b);
      }
      else
      {
         //----- If client, generate another
         
         //----- custom message and send it!
         
         byte[] b = GetMessage(e.Connection.SocketHandle.ToInt32());
         e.Connection.BeginSend(b);
      }
   }
   
   public override void OnDisconnected(DisconnectedEventArgs e)
   {
      //----- Check the host!
      
      if (e.Connection.HostType == HostType.htServer)
      {
         //----- Nothing!
         
      }
      else
      {
         //----- Reconnect with server!
         
         e.Connection.AsClientConnection().BeginReconnect();
      }
   }
}


The ISocketService implementation can be done in the same host assembly, or another assembly referenced by the host. This allows the user to separate the host implementation from the socket service, helping the administration in a server or a domain.

Connection Host


With the ISocketService created, you need to host the service and the service connections. Both the server and the client host have the same parent class, BaseSocketConnectionHost, which keeps a list of connections, encrypts and compresses the data buffers, enqueues the service requests and ensures that all data buffer has been sent or received, checks messages headers, and checks for idle connections. The CheckTimeoutTimer, periodically, at IdleCheckInterval, checks if the connections become idle, using the IdleTimeOutValue as the idle timeout. Header is the socket service header used by the host. HostType indicates if a host is a server or a client host. SocketBufferSize defines the size of the socket send and receive buffer. SocketService is the instance of ISocketService that drives the message exchange between the connections.


Connection Host

创建ISocketService接口后需要管理服务和连接。服务端和客户端主机实现同一个父类BaseSocketConnectionHost, 该类实现这些功能:管理连线列表,加密和压缩数据,查询服务请求, 确保所有数据发送或接收,检查消息头部和空闲的连接。CheckTimeoutTimer: 定期检查连接超时,IdleCheckInterval: 检查空闲连接的时间间隔, IdleTimeOutValue: 闲置连接超时间隔。Header:套接字服务头部消息.
HostType标识主机是服务端还是客户端。SocketBufferSize:定义发送和接收的字节数大小.SocketService是实现ISocketService接口的类实例,用于管理和交换连线之间的消息。


Encrypt and Compress



Every time you send and receive messages, the host checks if the data must be encrypted and/or compressed, and this work is made by the CryptUtils static class. The CreateSymmetricAlgoritm creates an ISymmetricAlgoritm based on the encryptType parameter. The DecryptData and DecryptDataForAuthenticate are used, respectively, to decrypt the received message and check the hash sign on the authenticate procedure. The EncryptData and EncryptDataForAuthenticate, respectively, encrypt the data to be sent and sign the authenticated message.


Encrypt and Compress 加密及解压

在任何时间发送和接收消息,主机需要检查数据是否是加密或压缩的,由静态类CryptUtils完成. CreateSymmetricAlgoritm方法创建一
个实现ISymmetricAlgoritm接口的类的实例, 由encryptType参数指定加密类型.也使用了DecryptData
和DecryptDataForAuthenticate方法。分别是解密收到的消息和解密通过授权程序哈希签名的消息。EncryptData
和EncryptDataForAuthenticate分别是加密发送的数据和消息授权签名。





The encrypted data buffer is labelled with the service header and the data buffer length, becoming a packet buffer. This packet buffer is controlled by the MessageBuffer class that keeps information about the packet buffer offset, length, the remaining bytes, and the raw buffer.

加密后的数据标记了消息头部及数据长度因此变成了另一个数据包, 该数据包由MessageBuffer类控制,它的功能是保持缓冲区的偏移量,
长度,剩余字节及原始缓冲区信息.


Check Message Header

If the socket service uses some header, all the send and receive processes need to create a packet message indicating the header and the message length. This packet label is created using the following structure:


检查消息头部

如在传输中需要使用消息头部, 发送和接收时需要处理包的消息头部及消息长度,使用下面的结构创建包的标签。





SocketServer and SocketListener





SocketServer Constructor and Methods



In the SocketServer constructor, the socketService parameter defines the ISocketService instance used by the server. The header parameters define the array of bytes used in the message header exchange. The socketBufferSize adjusts the socket buffer size. The messageBufferSize defines the maximum message size of the service. The idleCheckInterval indicates the interval for idle connections checking, in milliseconds. The idleTimeoutValue defines the timeout, in milliseconds, to be compared to each connection LastAction property.

To add SocketListener items in SocketServer, the method AddListener must be used. The localEndPoint parameter defines the local socket IP endpoint used to listen to connections. The encryptType and compressionType defines, respectively, the encryption and compression methods used in the new accepted connection. The cryptoService defines the ICryptoService used to authenticate the encryption method chosen. The backLog limits the listen queue of the OS socket to the defined number, and acceptThreads sets the calling number of the socket’s BeginAccept to increase the accepted performance.





SocketClient and SocketConnector




The SocketClient and SocketConnector are the classes needed to create a socket client. SocketClient is derived from BaseSocketConnectionHost and, like SocketServer, manages ISocketConnections. The SocketConnector is derived from BaseSocketConnectionCreator, and it connects with the socket server and creates a new ISocketConnection to be used. A SocketClient can have as many SocketConnectors attached as required, each one connecting to a socket server, and they can be assigned to a local address and a local port to start the connection.

SocketClient Constructor and Methods




原文:
http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx

www.csframework.com
版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
C/S框架网
上一篇:C#数据库本地缓存技术(Database local cache)
下一篇:ERP标准流程DOC文档下载
评论列表

发表评论

评论内容
昵称:
关联文章

异步实现Socket Server&Client
什么是C/S(Client/Server)架构的系统?
什么是Client/Server模块与源码共用?
ASP.NET WebApi框架异步实现MultipartContent方式上传文件
CSFramework.WebApi时钟定时作业异步处理程序(IThreadHandler接口)实现
C#异步编程(多线程)
C# WebService异步处理/异步调用详解
SQL Server 存储过程详解
C#异步操作等待窗体,异步多线程处理数据通用界面(frmThreadOperating)
CSFramework.WebApiV3.客户端 (Client Side)
CSFramework.WebApiV3.客户端 (Client Side)
DbProviderFactories 加载Oracle.DataAccess.Client 失败
C#多线程异步处理数据通用界面窗体(frmThreadOperating)
Sql Server历史版本号列表
提交GIT服务器失败,提示Git failed with a fatal error.Permission denied,.vs/Server/sqlite3/db.lock
CSFramework.EF 数据库框架 - 测试异步方法 (Async)
C# OOP编程 模拟做早餐探索同步异步机制
C#.Net版本自动更新程序及3种策略实现
SQL Server连接池基本原理
DevExpress GridView表格CustomUnboundColumnData事件异步加载图片

热门标签
.NET5 .NET6 .NET7 APP Auth-软件授权注册系统 Axios B/S B/S开发框架 Bug Bug记录 C#加密解密 C#源码 C/S CHATGPT CMS系统 CodeGenerator CSFramework.DB CSFramework.EF CSFrameworkV1学习版 CSFrameworkV2标准版 CSFrameworkV3高级版 CSFrameworkV4企业版 CSFrameworkV5旗舰版 CSFrameworkV6.0 DAL数据访问层 Database datalock DbFramework Demo教学 Demo下载 DevExpress教程 DOM EF框架 Element-UI EntityFramework ERP ES6 Excel FastReport GIT HR IDatabase IIS JavaScript LINQ MES MiniFramework MIS NavBarControl Node.JS NPM OMS ORM PaaS POS Promise API Redis SAP SEO SQL SQLConnector TMS系统 Token令牌 VS2022 VSCode VUE WCF WebApi WebApi NETCore WebApi框架 WEB开发框架 Windows服务 Winform 开发框架 Winform 开发平台 WinFramework Workflow工作流 Workflow流程引擎 版本区别 报表 踩坑日记 操作手册 代码生成器 迭代开发记录 基础资料窗体 架构设计 角色权限 开发sce 开发技巧 开发教程 开发框架 开发平台 开发指南 客户案例 快速搭站系统 快速开发平台 秘钥 密钥 权限设计 软件报价 软件测试报告 软件简介 软件开发框架 软件开发平台 软件开发文档 软件体系架构 软件下载 软著证书 三层架构 设计模式 生成代码 实用小技巧 收钱音箱 数据锁 数据同步 微信小程序 未解决问题 文档下载 喜鹊ERP 喜鹊软件 系统对接 详细设计说明书 行政区域数据库 需求分析 疑难杂症 蝇量级框架 蝇量框架 用户管理 用户开发手册 用户控件 在线支付 纸箱ERP 智能语音收款机 自定义窗体 自定义组件 自动升级程序