2013-05-15 1 views
0

기본적으로 두 개의 C# 응용 프로그램 인 클라이언트와 서버를 만들었습니다. 클라이언트는 소켓을 통해 서버에 연결 한 다음 텍스트가 포함 된 패킷을 보내고 서버는 응답해야합니다. 내 문제는 : 서버가 (또는 클라이언트가 응답 패킷을 닫을 때 (Alt + F4) 만 보냅니다. 나는 약간의 도움을 원한다. 두 프로젝트의 소스 코드 아래에 copypaste 할 것입니다. 클라이언트 :패킷을 닫을 때만 수신하는 클라이언트

public class StateObject 
{ 
    public Socket skt = null; 
    public const int BufferSize = 256; 
    public byte[] buffer = new byte[BufferSize]; 
    public StringBuilder sb = new StringBuilder(); 
} 

public class AsynchronousClient 
{ 
    private const int port = 11000; 
    private static ManualResetEvent connectDone = 
     new ManualResetEvent(false); 
    private static ManualResetEvent sendDone = 
     new ManualResetEvent(false); 
    private static ManualResetEvent receiveDone = 
     new ManualResetEvent(false); 
    private static String response = String.Empty; 
    public static string command; 
    public static Socket client; 
    public static void StartClient() 
    { 
     try 
     { 
      IPHostEntry ipHostInfo = Dns.GetHostEntry(IPAddress.Parse("127.0.0.1")); 
      IPAddress ipAddress = ipHostInfo.AddressList[0]; 
      IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port); 
      client = new Socket(AddressFamily.InterNetwork, 
      SocketType.Stream, ProtocolType.Tcp); 
      client.BeginConnect(remoteEP, 
       new AsyncCallback(ConnectCallback), client); 
      connectDone.WaitOne(); 
      while (true) 
      { 
       command = Console.ReadLine(); 
       if (command == "exit") 
       { 
        Console.WriteLine("Terminating..."); 
        client.Shutdown(SocketShutdown.Both); 
        client.Close(); 
        Environment.Exit(0); 
       } 
       else 
       { 
        Send(client, command + "<EOF>"); 
        sendDone.WaitOne(); 
        Receive(client); 
        receiveDone.WaitOne(); 
        Console.WriteLine("Response received : {0}", ProcessResponse(response)); 
        client.Shutdown(SocketShutdown.Both); 
        client.Close(); 
       } 
       //Console.CancelKeyPress += (sender, e) => 
       //{ 
       // Console.WriteLine("Terminating..."); 
       // client.Shutdown(SocketShutdown.Both); 
       // client.Close(); 
       // Environment.Exit(0); 
       //}; 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 
    static public string ProcessResponse(string pkt) 
    { 
     string response = null; 
     response = pkt.Replace("<EOF>",""); 
     return response; 
    } 
    private static void ConnectCallback(IAsyncResult ar) 
    { 
     try 
     { 
      Socket client = (Socket)ar.AsyncState; 
      client.EndConnect(ar); 
      Console.WriteLine("Socket connected to {0}", 
       client.RemoteEndPoint.ToString()); 
      connectDone.Set(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void Receive(Socket client) 
    { 
     try 
     { 
      StateObject state = new StateObject(); 
      state.skt = client; 
      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
       new AsyncCallback(ReceiveCallback), state); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void ReceiveCallback(IAsyncResult ar) 
    { 
     try 
     { 
      StateObject state = (StateObject)ar.AsyncState; 
      Socket client = state.skt; 
      int bytesRead = client.EndReceive(ar); 
      if (bytesRead > 0) 
      { 
       state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
       client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
        new AsyncCallback(ReceiveCallback), state); 
      } 
      else 
      { 
       if (state.sb.Length > 1) 
       { 
        response = state.sb.ToString(); 
       } 
       receiveDone.Set(); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void Send(Socket client, String data) 
    { 
     byte[] byteData = Encoding.ASCII.GetBytes(data); 
     client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client); 
    } 

    private static void SendCallback(IAsyncResult ar) 
    { 
     try 
     { 
      Socket client = (Socket)ar.AsyncState; 
      int bytesSent = client.EndSend(ar); 
      Console.WriteLine("Sent {0} bytes to server.", bytesSent); 
      sendDone.Set(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    public static int Main(String[] args) 
    { 
     StartClient(); 
     return 0; 
    } 

서버 : 클라이언트에서

public class Program 
{ 
    public class StateObject 
    { 
     public Socket skt = null; 
     public const int buffersize = 1024; 
     public byte[] buffer = new byte[buffersize]; 
     public StringBuilder sb = new StringBuilder(); 
    } 
    public class AsynchronousSocketListener 
    { 
     public static ManualResetEvent allDone = new ManualResetEvent(false); 
     public AsynchronousSocketListener() { } 
     public static Socket handler; 
     public static void StartListening() 
     { 
      byte[] bytes = new Byte[1024]; 
      IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); 
      IPAddress ipAddress = ipHostInfo.AddressList[0]; 
      IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); 

      Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      try 
      { 
       listener.Bind(localEndPoint); 
       listener.Listen(100); 
       while (true) 
       { 
        allDone.Reset(); 
        Console.WriteLine("Waiting for a connection..."); 
        listener.BeginAccept(
         new AsyncCallback(AcceptCallback), 
         listener); 
        allDone.WaitOne(); 
       } 

      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.ToString()); 
      } 

      Console.WriteLine("\nPress ENTER to continue..."); 
      Console.Read(); 
     } 
     public static void AcceptCallback(IAsyncResult ar) 
     { 
      allDone.Set(); 
      Socket listener = (Socket)ar.AsyncState; 
      Socket handler = listener.EndAccept(ar); 
      StateObject state = new StateObject(); 
      state.skt = handler; 
      handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0, new AsyncCallback(ReadCallback), state); 
     } 
     public static void ReadCallback(IAsyncResult ar) 
     { 
      String content = String.Empty; 
      StateObject state = (StateObject)ar.AsyncState; 
      Socket handler = state.skt; 
      int bytesRead = handler.EndReceive(ar); 

      if (bytesRead > 0) 
      { 
       state.sb.Append(Encoding.ASCII.GetString(
       state.buffer, 0, bytesRead)); 
       content = state.sb.ToString(); 
       if (content.IndexOf("<EOF>") > -1) 
       { 
        Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, ProcessResponse(content)); 
        Send(handler, content); 
       } 
       else 
       { 
        handler.BeginReceive(state.buffer, 0, StateObject.buffersize, 0, 
        new AsyncCallback(ReadCallback), state); 
       } 
      } 
     } 
     private static void Send(Socket handler, String data) 
     { 
      byte[] byteData = Encoding.ASCII.GetBytes(data); 
      handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); 
     } 
     private static void SendCallback(IAsyncResult ar) 
     { 
      try 
      { 
       handler = (Socket)ar.AsyncState; 
       int bytesSent = handler.EndSend(ar); 
       Console.WriteLine("Sent {0} bytes to client.", bytesSent); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.ToString()); 
      } 
     } 
     static public string ProcessResponse(String pkt) 
     { 
      string response = null; 
      response = pkt.Replace("<EOF>", ""); 
      return response; 
     } 
    } 
    public static void Main(string[] args) 
    { 
     AsynchronousSocketListener.StartListening(); 
    } 
} 

답변

1

수신 콜백 : 소켓이 명시 적으로하지 않는 한 당신은 이제까지 else 블록으로 드롭 다운되지 않습니다

private static void ReceiveCallback(IAsyncResult ar) 
{ 
    try 
    { 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket client = state.skt; 
     int bytesRead = client.EndReceive(ar); 
     if (bytesRead > 0) 
     { 
      state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
       new AsyncCallback(ReceiveCallback), state); 
     } 
     else 
     { 
      if (state.sb.Length > 1) 
      { 
       response = state.sb.ToString(); 
      } 
      receiveDone.Set(); 
     } 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

닫혔습니다 (또는 연결에 다른 종류의 오류가 있습니다). 그러므로 receiveDone은 결코 설정되지 않으며 메인 루프는 단순히 "응답"을 기다리며 붙어 있습니다.

이 오면 당신이 "완료 메시지"를 처리 할 경우이처럼 버퍼에 현재 문자열을 추가 한 후, 다음 <EOF> 값을 확인 :

응답 메커니즘을 사용하는 것으로
  if (bytesRead > 0) 
      { 
       state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 

       // it's not a "response" unless it's terminated with "<EOF>" right? 
       response = state.sb.ToString(); 
       if (response.IndexOf("<EOF>") != -1) 
       { 
        state.sb.Clear(); 
        receiveDone.Set(); 
       } 
       else 
       { 
        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
         new AsyncCallback(ReceiveCallback), state); 
       } 
      } 
      else 
      { 
       if (state.sb.Length > 1) 
       { 
        response = state.sb.ToString(); // this is a partial response, not terminated with "<EOF>" 
       } 
       receiveDone.Set(); 
      } 

같은 시간에 여러 메시지가 들어오지 못해 극도로 제한됩니다. Hello<EOF> World!<EOF> 두 메시지를 하나의 긴 메시지로 취급합니다. (귀하의 예는 하나의 "메시지"만 보내고 있음을 알고 있습니다.)

"콘텐트"메시지 외에 "제어"메시지를 보내는 실제 응용 프로그램에서이 시나리오를 처리해야합니다. 이 문제를 처리하려면 IndexOf()를 사용하여 <EOF>을 찾고 그 지점까지 텍스트를 추출하고 "complete message"를 처리하십시오. 이후에도 다른 보류중인 메시지를 처리하기 위해 여전히 <EOF>이 발견되면 루핑을 계속합니다. <EOF> 뒤에 남아있는 값을 남겨 두어 부분 메시지가 들어올 때 기존 데이터에 새 데이터를 추가 할 수 있도록 StringBuilder에서 처리 된 전체 메시지를 제거해야합니다. 데이터를 전송할 때 데이터가 분할되어 여러 개의 "청크"가 수신 되었기 때문에 데이터를 전송할 때 논리적으로 하나의 "완료 메시지"인 경우에도 데이터가 수신 될 수 있기 때문입니다. 따라서 Complete Message<EOF>을 사용하여 보내는 사람은 Comp과 같은 수신자가 이어질 수 있으며 그 다음에 lete Message<EOF>이옵니다. 귀하의 코드는 이러한 TCP 통신의 현실을 처리 할 수 ​​있어야합니다.

+0

Thank you! 정말 도움이되었습니다. 방금 소켓이 작동하는 방법을 배우기 시작했습니다 (2 주 동안 자체 교습 된 csharp 사용 경험이 있습니다). – trapped

+0

내 [기사] (http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/A_11178-A-Peer-To-Peer-LAN-Chat-Application-in- Visual Basic-Net-TcpClient-and-TcpListener.html) ... VB.Net에 있지만 개념은 여전히 ​​적용됩니다. –

관련 문제