2012-12-04 98 views
1

我是編程新手,我正在研究異步客戶端服務器應用程序。 我可以從客戶端向服務器發送消息,但是當我將數據接收到服務器(OnDataReceived方法)並嘗試將相同的數據發送回客戶端(用於測試目的)時,我不能。 不知道我需要給予什麼其他信息,所以請讓我知道,我不是故意含糊不清。異步客戶端服務器通信問題

服務器代碼

public void OnDataReceived(IAsyncResult asyncResult) 
    { 
     try 
     { 
      SocketPacket socketData = (SocketPacket)asyncResult.AsyncState; 
      int iRx = 0; 
      iRx = socketData.currentSocket.EndReceive(asyncResult); 
      char[] chars = new char[iRx]; 
      Decoder decoder = Encoding.UTF8.GetDecoder(); 
      int charLen = decoder.GetChars(socketData.dataBuffer, 0, iRx, chars, 0); 
      String receivedData = new String(chars); 

      //BroadCast(receivedData); 

      this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => lbxMessages.Items.Add(receivedData))); 

      //Updated Code 
      this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => broadcast(receivedData))); 

      WaitForData(socketData.currentSocket); 


     } 
     catch (ObjectDisposedException) 
     { 
      System.Diagnostics.Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n"); 
     } 
     catch (SocketException se) 
     { 
      MessageBox.Show(se.Message); 
     } 
    } 

public class SocketPacket 
    { 
     public Socket currentSocket; 
     public byte[] dataBuffer = new byte[50];//allowing the 50 digist to be sent at once 
    } 

    private void WaitForData(Socket socket) 
    { 
     try 
     { 
      if (workerCallBack == null) 
      { 
       workerCallBack = OnDataReceived; 
      } 
      SocketPacket sckPack = new SocketPacket(); 
      sckPack.currentSocket = socket; 
      socket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, workerCallBack, sckPack); 
     } 
     catch(SocketException se) 
     { 
      MessageBox.Show(se.Message); 
     } 
    } 

響應更新爲Andrew的答覆

我有當客戶端連接

private void OnClientConnect(IAsyncResult asyncResult) 
    { 
     try 
     { 
      //Here we complete/end the Beginaccept() asynchronous call by 
      //calling EndAccept() - which returns the reference to a new socket object 
      workerSocket[clientCount] = listenSocket.EndAccept(asyncResult); 

      //Let the worker socket do the further processing for the just connected client 
      WaitForData(workerSocket[clientCount]); 

      //Now increment the client count 
      ++clientCount; 

      if (clientCount<4)//allow max 3 clients 
      { 
       //Adds the connected client to the list 
       connectedClients.Add(listenSocket); 
       String str = String.Format("Client # {0} connected", clientCount);     

       this.Dispatcher.Invoke((Action)(() => 
       { 
        //Display this client connection as a status message on the GUI 
        lbxMessages.Items.Add(str); 
        lblConnectionStatus.Content =clientCount + " Connected"; 
       })); 

       //Since the main Socket is now free, it can go back and wait for 
       //other clients who are attempting to connect 
       listenSocket.BeginAccept(OnClientConnect, null); 
      } 
     } 
     catch (ObjectDisposedException) 
     { 
      System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n"); 
     } 
     catch (SocketException) 
     { 
      HandleClientDisconnect(listenSocket); 
     } 
    } 

(修訂版) ADDED METHOD TO將被調用的方法由服務器返回給客戶的廣播消息

public void broadcast(string msg) 
    { 
     //foreach (Socket item in connectedClients) 
     //{ 
     Socket broadcastSocket; 
     broadcastSocket = workerSocket[0]; //sends message to first client connected 
     byte[] broadcastBytes = null; 
     broadcastBytes = Encoding.ASCII.GetBytes(msg); 
     broadcastSocket.Send(broadcastBytes); 
     //} 
    } 
+1

你是什麼意思,你不能發送數據回客戶端?你收到什麼錯誤? 順便說一句,如果你是新手編程,從同步版本開始,然後才移動到異步。 –

+0

錯誤讀取'發送或接收數據的請求被禁止,因爲套接字未連接,並且(當使用sendto調用在數據報套接字上發送時)沒有提供地址' –

+0

讀取您的更新,我相信你應該寫信給您在workerSocket [ClientCount]中保留的套接字。在Clientcount上,與你的問題沒有關係,但你可能想調試你如何使用它 - 你似乎正在向數組寫入數據 - workerSocket [ClientCount];那麼你後來增加了,然後可能/可能沒有對它做任何工作。在我看來,第四個客戶端將被添加到WorkerSocket;也有一個WaitForData發出,但沒有添加到connectedClient等 – andrew

回答

0

服務器端TCP通信涉及兩個套接字。第一個套接字是一個監聽套接字,你只能用它來接受新的請求。然後,每當您接受來自客戶端的新請求時,您都會爲每個連接獲得另一個套接字。

您嘗試通過監聽套接字但不是通過你接受的套接字發回數據。

0

謝爾蓋說得對。如果您希望有一臺服務器處理多個客戶端,那麼您需要某種類型的ServerTerminal類,它可以偵聽新的連接,然後設置某種「connectedclient」類來處理該套接字的IO。您的「OnDataReceived」方法將位於connectedclient類中。

在您的插座接受例行它應該是這個樣子:

private void OnClientConnection(IAsyncResult asyn) 
    { 
     if (socketClosed) 
     { 
      return; 
     } 

     try 
     { 
      Socket clientSocket = listenSocket.EndAccept(asyn); 

      ConnectedClient connectedClient = new ConnectedClient(clientSocket, this, _ServerTerminalReceiveMode); 

      connectedClient.StartListening(); 

在你傳入一個插座接受常規 - 我命名這個「ClientSocket的」。這是您要寫入的套接字,而不是偵聽套接字。

+0

我有一個方法來處理客戶端連接,如果這就是你說的話。 –