2013-05-15 27 views
0

基本上,我制作了两个C#应用程序,即客户端和服务器。客户端连接到服务器(通过套接字),然后发送包含一些文本的数据包,服务器应该回复。 我的问题是:服务器仅在关闭时发送(或客户端接收)响应数据包(ALT + F4)。我想要一些帮助。我会在两个项目的源代码下面复制粘贴。 客户:客户端仅在关闭时接收数据包

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

在你客户收到回调:

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()); 
    } 
} 

你永远不会下拉到else块,除非插座是明确关闭(或在连接中存在某种其他错误)。因此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>来处理其他未决消息,就会持续循环。您还必须删除StringBuilder中已处理的完整消息,以便<EOF>之后的任何剩余值保留原位,以便在部分消息进入时,可以将新数据附加到现有数据。这是因为您的数据在发送时也可能会分裂,导致数据被“接收”多个“块”,即使它在发送时在逻辑上是一个“完整消息”。所以用Complete Message<EOF>发送的一个可以导致一个或多个接收,例如Comp,然后是lete Message<EOF>。你的代码必须能够处理TCP通信的这些现实...

+0

谢谢!真的有帮助。我刚开始学习套接字的工作方式(只有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-using-TcpClient-and-TcpListener.html)...它在VB.Net中,但这些概念仍然适用。 –