2012-12-04 2 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); 
     } 
    } 

나는 클라이언트가

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 방법에 연결 될 때 호출하는 방법을 클라이언트가 서버에서 수신 한 방송 메시지

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

데이터를 클라이언트로 다시 보낼 수 없다는 것은 무엇을 의미합니까? 어떤 오류가 발생합니까? BTW 프로그래밍을 처음 사용하는 경우 동기식 버전부터 시작한 다음 비동기식으로 만 이동하십시오. –

+0

소켓이 연결되어 있지 않고 (sendto 호출을 사용하여 데이터 그램 소켓을 통해 보낼 때) 주소가 제공되지 않았기 때문에 '데이터 송수신 요청이 허용되지 않았습니다.' –

+0

업데이트를 읽으면 서면으로 작성해야합니다. workerSocket [ClientCount]에 보관중인 소켓입니다. Clientcount에서 질문과 관련이 없지만 이것을 사용하는 방법을 디버깅하고자 할 수 있습니다. 배열에 데이터를 쓰는 것처럼 보입니다. workerSocket [ClientCount]; 나중에 당신은 증가하고, 어쩌면/아마도 그것으로 작업을하지 않을 것입니다. 4 번째 클라이언트가 WorkerSocket에 추가 될 것입니다. 또한 WaitForData가 발행되었지만 connectedClient 등에 추가되지 않았습니다. – andrew

답변

0

서버 측 TCP 통신에는 2 개의 소켓이 있습니다. 첫 번째 소켓은 청취 소켓이며 새 요청을 수락 할 때만 사용해야합니다. 그런 다음 클라이언트의 새로운 요청을 수락 할 때마다 모든 연결에 대해 다른 소켓을 얻게됩니다.

청취 소켓을 통해 데이터를 보내려고했지만 받아 들인 소켓을 통해 데이터를 보내려하지 않았습니다.

0

세르게이가 맞습니다. 한 서버에서 여러 클라이언트를 처리하도록하려면 새로운 연결을 수신 한 다음 소켓의 IO를 처리하는 일종의 "connectedclient"클래스를 설정하는 일종의 ServerTerminal 클래스가 필요합니다. "OnDataReceived"메소드는 연결된 클라이언트 클래스에 있습니다. 당신의 소켓에서

는 같은 보일 것 루틴을 동의 : 당신이 소켓을 통과하고있는 동의 루틴에서

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

나는 당신의 대화에 대해 클라이언트가 연결하는 방법을 알고 있습니다. –