2013-06-30 205 views
0

我有一個TCP IP服務器應用程序接受多個客戶端並處理他們的請求。管理連接的TCP客戶端

其中之一,我需要處理被髮送到客戶端的反應遲緩,更具體的情況,這裏是我的設計細節和協議:

A)客戶端發送一個請求做的工作,並且服務器成功接收並啓動該作業。

B)服務器,時間長了以後,需要搜索該客戶端連接,並告訴他,他的工作完成

我的方法是如下:

  • 在客戶端的連接,我生成一個Class的新實例,該實例持有剛剛連接的客戶端實例和唯一的令牌,以便我可以跟蹤客戶端請求並異步回覆他,讓我們稱這個類爲MyConnectedClient

  • 然後,我插入這個MyConnectedClient實例到客戶的Hashtable,獨特的令牌是他的鑰匙,和值是MyConnectedClient


  • 實例現在,當作業已完成,具體取決於傳遞給作業的客戶端令牌,我可以從已連接的客戶端列表中檢索客戶端並將備忘錄發送給客戶端。此外,當客戶端連接死亡時,我引發事件並將令牌與其一起發送,因此,我的服務器將從連接的客戶端列表中刪除MyConnectedClient實例。


基本上,這是我的用戶管理設計,正如我所說,這是工作的罰款和足夠我的需要,但問題是,有沒有更好的方式來處理連接的客戶端?

去除死皮的客戶或者找一個客戶端,較早提出的要求?

完成下面的代碼示例:

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

namespace TCPIPIPC.Server 
{ 
    public class Server 
    { 
     int publicToken = 0; 

     public class ConnectedClient 
     { 
      public TcpClient tcpClient; 
      public DateTime connectedSince; 
      public int token; 
     } 

     Hashtable ClientList; 

     #region Variable declaration 
     /// <summary> 
     /// Main TCP listener 
     /// </summary> 
     private TcpListener tcpListener; 

     /// <summary> 
     /// Main server thread 
     /// </summary> 
     private Thread listenThread; 

     /// <summary> 
     /// Event handler for received message from the server 
     /// </summary> 
     /// <param name="message"></param> 
     public delegate void ServerMessageEventHandler(string message, ConnectedClient client); 

     /// <summary> 
     /// Event handler for connected client to the server 
     /// </summary> 
     /// <param name="tcpClient"></param> 
     public delegate void clientconnectedEventHandler(ConnectedClient client); 

     /// <summary> 
     /// Event to be raised when data received from the server 
     /// </summary> 
     public event ServerMessageEventHandler MessageReceived; 

     /// <summary> 
     /// Event to be raised when a client is Connected/Disconnected to the server 
     /// </summary> 
     public event clientconnectedEventHandler ClientConnected; 
     public event clientconnectedEventHandler ClientDisconnected; 

     public IList Items; 
     #endregion 

     /// <summary> 
     /// Constructor, Server initialization 
     /// </summary> 
     public Server(IPAddress listenerAddress, int listenerPort) 
     { 
      ClientList = new Hashtable(); 
      ClientDisconnected += new clientconnectedEventHandler(Server_ClientDisconnected); 
      this.tcpListener = new TcpListener(listenerAddress, listenerPort); //new TcpListener(IPAddress.Any, 3000); 
      this.listenThread = new Thread(new ThreadStart(ListenForClients)); 
      this.listenThread.Start(); 
     } 

     /// <summary> 
     /// Remove disconnected clients 
     /// </summary> 
     /// <param name="client"></param> 
     void Server_ClientDisconnected(Server.ConnectedClient client) 
     { 
      if (ClientList.ContainsKey(client.token)) 
      { 
       ClientList.Remove(client.token); 
      } 
     } 

     /// <summary> 
     /// Main listener thread start 
     /// </summary> 
     private void ListenForClients() 
     { 
      this.tcpListener.Start(); 
      while (true) 
      { 
       //blocks until a client has connected to the server 
       TcpClient client = this.tcpListener.AcceptTcpClient(); 

       var connecteItem = new ConnectedClient(); 

       connecteItem.tcpClient = client; 
       connecteItem.connectedSince = DateTime.Now; 
       connecteItem.token = publicToken++; 

       //create a thread to handle communication 
       //with connected client 
       Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm)); 
       clientThread.Start(client); 

       //Raise client connected event 
       if (ClientConnected != null) 
       { 
        ClientConnected(connecteItem); 
       } 
      } 
     } 

     /// <summary> 
     /// Client communication handler 
     /// </summary> 
     /// <param name="client">the received connection from the client of type TcpClient</param> 
     private void HandleClientComm(object client) 
     { 
      ConnectedClient currentClient = (ConnectedClient)client; 
      TcpClient tcpClient = currentClient.tcpClient; 
      NetworkStream clientStream = tcpClient.GetStream(); 

      byte[] message = new byte[4096]; 
      int bytesRead; 

      while (true) 
      { 
       bytesRead = 0; 

       try 
       { 
        //blocks until a client sends a message 
        bytesRead = clientStream.Read(message, 0, 4096); 
       } 
       catch 
       { 
        //a socket error has occurred 
        break; 
       } 

       if (bytesRead == 0) 
       { 
        //the client has disconnected from the server 
        break; 
       } 

       //message has successfully been received 
       ASCIIEncoding encoder = new ASCIIEncoding(); 

       //Raise message received event 
       if (MessageReceived != null) 
       { 
        MessageReceived(encoder.GetString(message, 0, bytesRead), currentClient);//This will be caught by a parent worker who will start a job based on this request 
       } 

       //System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead)); 
      } 

      tcpClient.Close(); 

      if (ClientDisconnected != null) 
      { 
       ClientDisconnected(currentClient); 
      } 
     } 

     /// <summary> 
     /// This method sends a message to a connected client 
     /// </summary> 
     /// <param name="tcpClient">The connected TcpClient client instance to send a message to</param> 
     /// <param name="message">The message to send to the client</param> 
     public void SendMessage(TcpClient tcpClient, string message) 
     { 
      NetworkStream clientStream = tcpClient.GetStream(); 
      ASCIIEncoding encoder = new ASCIIEncoding(); 
      byte[] buffer = encoder.GetBytes(message); 

      clientStream.Write(buffer, 0, buffer.Length); 
      clientStream.Flush(); 
     } 
    } 
} 

請不高於該代碼沒有完全定型,但它說明了想法

回答

1

只是作業的客戶端套接字相關聯,並有工作任務寫入對該套接字的響應。如果失敗,客戶端已斷開連接。你並不需要所有其他爵士樂。

+0

好點,謝謝 – simsim