异步服务器端与客户端模型(一)

原文地址:http://www.codeproject.com/cs/internet/AsyncSocketServerandClien

原文可能已经不在,找到的转载地址:http://usbforum.cn/?action-viewnews-itemid-17332

以下是译文:

2000年开始,我就使用Delphi5.0和一些第三方组件类库从事套接字方面的开发工作,我的第一个socket应用程序只是从很多客户端和服务器之间进行文件的拷贝。客户端检测一个文件夹目录查看文件是否存在,在网络上询问服务器从哪里可以拷贝,紧随着进行拷贝、标记数据库记录并指出这个文件已经被移动过(磁盘位置)。服务器监听着客户端之间的连接,彼此进行XML信息交换,指出每个文件拷贝的情况。Synapse是一个阻塞型套接字实现,而我需要一个类似于HTTP服务器的线程池结构,因为我不能让连接一直保持打开(一个线程一个连接)。我的解决方案是用一些IOCP(完成端口)函数去装载(这些)连接请求并在信息处理完毕之后关闭这些连接。

         现在,我决定用C#先编写服务器和客户端组件,这样,我可以只考虑信息交换(之间的逻辑而不用再去关心数据的传输问题)以及用.NET平台来实现这个艰难的工作。所以,需要完成以下几个重点:

1.        异步处理。

2.        一些加密和压缩技术的支持。

3.        封装套接字,将服务请求从host实现层分离出来并使用接口对它们进行加密。

 

Socket Connection

异步服务器端与客户端模型(一)_第1张图片

ISocketConnection是所有socket连接的基接口,它描述了所有连接的属性和方法。ConnectionID属性利用GUID译注:Guid是一个使用16进制位定义的全球唯一标识符)值定义了一个唯一的连接。CustomerData属性定义了一个与连接相关联的客户对象。Header属性是一个socket服务头用于每个被封装在消息包里面的消息。只有一个定义了头信息的消息才会被接受。LocalEndPointRemoteEndPoint是用于连接的两个套接字终端。而SocketHandle是交付操作系统控制的句柄。

IClientSocketConnectionIServerSocketConnection继承自ISocketConnection,各自又具有自己的函数。IClientSocketConnection能使用BeginReconnect方法重新连接服务器,IServerSocketConnection在服务器主机可以用BeginSendTo以及BeginSendToAll方法与其他连接进行通讯,并且能通过GetconnectionById方法获得ConnectionId。每个连接从自身识别主机、加密、压缩类型以及能发送、接受和自己断开(连接)。这个接口被用于ISocketService接口,它允许用户去整合socket连接。

异步服务器端与客户端模型(一)_第2张图片

在组件的内部实现上,所有连接的创建都是来自于基本连接的实现:BaseSocketConnection, ClientSocketConnection, 以及 ServerSocketConnection

 

Socket Services

异步服务器端与客户端模型(一)_第3张图片

ISocketService接口描述了连接的事件,这些事件由主机(译注:这里的主机指的是服务器或者客户端)触发,并且带有一个ConnectionEventArgs参数,该参数另外携带了一个可以唯一表示那个连接的ISocketConnection接口对象,在OnReceivedOnSent事件里面,一个带有发送和接受字节数组的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();
        }
    }
}

ISocketService 能够被同一台主机的assembly程序集所实现,或者被主机的另一个程序集所引用。它允许用户将Socket services的主机实现相分离,从而方便在一台服务器或者一个域名中管理。

(文章比较长,未完待续...)

你可能感兴趣的:(网络编程)