2013-10-07 25 views
3

我试图写在C#中,它从多个客户端接收数据的简单的多线程TCP服务器不会阻止。C#Socket.receive连续接收0字节,以及环

每当一个新的客户端连接,插座连接建立和插座被作为参数传递给新的类函数传递,之后while循环运行,并直到客户端连接接收数据。

的这里的问题是,“socket.receive”是不会阻止并接收0字节的数据。所以循环连续运行,而不会阻塞在代码中的socket.receive(“clientSocket.Receive(bb)”)。

我使用Chrome浏览器作为客户端进行测试。 即使我使用任何其他客户端,TCP服务器的行为仍保持不变。

客户端只发送一次数据,但服务器连续收到0字节,while循环继续运行。

我正在粘贴服务器输出以供参考。

请帮助阻止服务器在socket.receive等待下一个客户端传输。 奇怪的是,即使接收到0字节,异常也不会被调用。

请帮忙。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 
Threading; 
using System.Timers; 
using System.Security; 
using System.Security.Permissions; 
namespace SERVER 
{ 
    static class Constants 
    { 
     public const int port = 8080; 
     public const int buffer_size = 512; 


    } 
    class Program 
    { 
     static public string LocalIPAddress() 
     { 
      IPHostEntry host; 
      string localIP = ""; 
      host = Dns.GetHostEntry(Dns.GetHostName()); 
      foreach (IPAddress ip in host.AddressList) 
      { 
       if (ip.AddressFamily == AddressFamily.InterNetwork) 
       { 
        localIP = ip.ToString(); 
        break; 
       } 
      } 
      return localIP; 
      //return ip; 
     } 

     static void Main(string[] args) 
     { 
      //IPEndPoint ipObj = new IPEndPoint(IPAddress.Parse("Server IP goes here"), 20487); //20487 is port. you can change it according to your wish 
      System.Net.IPAddress IP = IPAddress.Any; 
      int port = Constants.port; 
      TcpListener listnerObj = new TcpListener(IP, port); 
      listnerObj.Start(); 
      string client_addr; 
      string[] client_addr_split; 
      string IP_string = LocalIPAddress(); 

      Console.WriteLine("Server Started on {0}:{1}", IP_string, port); 
      while (true) 
      { 
       Console.WriteLine("================================"); 
       Console.WriteLine("** Waiting For Client  **"); 
       Socket clientSocket = listnerObj.AcceptSocket(); // waiting for the client to connect 

       client_addr = clientSocket.RemoteEndPoint.ToString(); 
       client_addr_split = client_addr.Split(':'); 
       client_addr = client_addr_split[0]; 

       Console.WriteLine("Client Connected {0}", client_addr); 
       ParameterizedThreadStart thread = delegate { new communication().doCommunicate(clientSocket, client_addr); }; 
       Thread th = new Thread(thread); 
       th.Start(); // start the thread here 
      } 
     } 

     class communication 
     { 
      public int byteReceived; 
      public byte[] bb; 
      public void doCommunicate(Socket clientSocket, string client_addr) 
      { 
       clientSocket.Blocking = true; 
       bb = new byte[Constants.buffer_size]; 

       //Console.WriteLine("***** Entered DoCommunicate *****"); 
       while (clientSocket.Connected) 
       { 
        //Console.WriteLine("Entered While"); 
        try 
        { 
         //Console.WriteLine("Entered TRY"); 
         Console.WriteLine("Waiting to recieve Data from IP : client_addr"); 
         //int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None); 
         byteReceived = clientSocket.Receive(bb, 0, bb.Length, SocketFlags.None); 
         //byteReceived = clientSocket.Receive(bb); 
        } 
        catch (SocketException e) 
        { 
         Console.WriteLine("Error: Socket Exception.\n{0}\n{1}.", e.Message, e.ErrorCode); 
         break; 
        } 
        catch (ArgumentNullException e) 
        { 
         Console.WriteLine("Error : Argument Null Exception.\n{0}", e.Message); 
         break; 
        } 
        catch (ObjectDisposedException e) 
        { 
         Console.WriteLine("Error : Socket Disposed Exception Caught.\n{0}", e.Message); 
         break; 
        } 
        catch (SecurityException e) 
        { 
         Console.WriteLine("Error: Security Exception.\n{0}", e.Message); 
         break; 
        } 
        //clientSocketglobal.Send(Encoding.Default.GetBytes("Hello Client"), SocketFlags.None); 
        Console.WriteLineWriteLine("Received Byte count : {0}, from IP : {1}", byteReceived, client_addr); // Do whatever you want to do with the data recieved. Parsing and storing etc. 
        Console.WriteLine(Encoding.UTF8.GetString(bb)); 
       } 
       //Console.WriteLine("While Loop Exited"); 
       Console.WriteLine("Socked and Class Object Disposed"); 
       clientSocket.Close(); 
       clientSocket.Dispose(); 
       GC.Collect(); 
      } 
     } 
    } 
} 

输出服务器:

Server Started on 10.0.0.2:8080 
================================ 
** Waiting For Client  ** 
Client Connected 10.0.0.2 
================================ 
** Waiting For Client  ** 
Client Connected 10.0.0.2 
================================ 
** Waiting For Client  ** 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 386, from IP : 10.0.0.2 
GET /HelloWorld HTTP/1.1 
Host: 10.0.0.2:8080 
Connection: keep-alive 
Cache-Control: max-age=0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6 


Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Waiting to recieve Data from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 
Received Byte count : 0, from IP : 10.0.0.2 

回答

4

如果收到0字节,这通常意味着发件人已关闭了他们的发送套接字。在一个Socket,所述发送接收信道是分开的;我期望发生的事情是你的发送(他们的接收)仍然是开放和可用的,因此clientSocket.Connected返回true(你仍然可以给他们发送回复),但是:他们一发送他们的有效载荷就立即关闭他们的发送(你的接收) (这很常见,以指示批次的结束)。基本上,你只需要检测0字节接收,并把那作为结束:没有更多的数据将永远是传入一旦你不得不从收到未正面回复。因此,只需编写任何需要编写的响应(他们仍然可以听,即使他们再也不会说话),然后关闭套接字。

补充说明:在HTTP/1.1 Connection: keep-alive,该可以保持自己的插座打开准备发送下一个请求 - 但它只是看起来像在这种情况下,他们根本没有。他们在发出请求后立即关闭套接字。这很好。只需提供响应并完全关闭套接字。没有更多的请求会传入。

+0

谢谢马克,但如果是这样的话,为什么没有例外引发? – Ashish

+2

@Ashish为什么会引发异常?你正在询问数据,它说“没有更多的数据 - 永远”。然后你问它的数据:它说“没有更多的数据 - 永远”。然后你问它的数据:它说“没有更多的数据 - 永远”。然后你问它的数据:它说“没有更多的数据 - 永远”。这里没有什么特别值得...只是:注意答复。电脑不会厌烦说“不”。 –

+0

谢谢Marc,我明白了。有没有更好的接收数据的方法? – Ashish