2013-03-31 53 views
1

我使用插座.NET中的代理服務器上的工作,我已經發現了代碼執行非常感興趣的時刻:C#代理服務器不正常工作

  1. 當調試代碼一步一步 - 代理服務器工作正常
  2. 當我啓動代理服務器而無需調試 - 我在瀏覽器中出現錯誤。

我真的不知道爲什麼它像我上面描述的那樣工作。也許,有人已經解決了這個問題了?

這裏是我的代理服務器的代碼:

using System; 
using System.Collections.Generic; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading; 

namespace Statistiks.Lib 
{ 
    internal class NetworkMonitor 
    { 
     private readonly IList<string> _denied; 
     private readonly Socket _srvSocket; 
     private readonly Thread _srvThread; 

     public NetworkMonitor(int port, IList<string> deniedList) 
     { 
      _denied = deniedList; 
      _srvSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 
            ProtocolType.Tcp); 
      _srvSocket.Bind(new IPEndPoint(IPAddress.Loopback, port)); 
      _srvThread = new Thread(ProxyServerThread); 
      _srvThread.Start(_srvSocket); 
     } 

     private void ProxyServerThread(object obj) 
     { 
      var srv = obj as Socket; 
      srv.Listen(1024); 
      while (true) 
      { 
       Socket clientSocket = srv.Accept(); 
       ThreadPool.QueueUserWorkItem(cSocket => 
        { 
         var client = cSocket as Socket; 
         if (client.Available <= 0) 
         { 
          client.Shutdown(SocketShutdown.Both); 
          client.Close(); 
          return; 
         } 
         var recieveBuf = new byte[client.Available]; 
         client.Receive(recieveBuf, SocketFlags.None); 
         var ni = new NetworkInfo(); 
         try 
         { 
          ni.Url = new Uri(Encoding.ASCII.GetString(recieveBuf) 
                .Split(new[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries)[0] 
               .Split(' ')[1]); 
         } 
         catch (ArgumentOutOfRangeException) 
         { 
          client.Shutdown(SocketShutdown.Both); 
          client.Close(); 
          return; 
         } 
         var forwardedSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 
                 ProtocolType.Tcp); 
         forwardedSocket.Connect(Dns.GetHostAddresses(ni.Url.Host)[0], ni.Url.Port); 
         forwardedSocket.Send(recieveBuf, SocketFlags.None); 
         recieveBuf = new byte[forwardedSocket.Available]; 
         forwardedSocket.Receive(recieveBuf, SocketFlags.None); 
         client.Send(recieveBuf, SocketFlags.None); 
         forwardedSocket.Shutdown(SocketShutdown.Both); 
         forwardedSocket.Disconnect(false); 
         client.Shutdown(SocketShutdown.Both); 
         client.Disconnect(false); 
         forwardedSocket.Close(); 
         client.Close(); 
        }, clientSocket); 
      } 
     } 
    } 

    internal struct NetworkInfo 
    { 
     internal Uri Url; 
    } 
} 
+0

聽起來像時間問題。很有可能在收到任何數據之前檢查可用數據,導致連接關閉。此外,使用while循環來接收數據(其中一些可能已準備好閱讀,但可能還沒有完成)。 –

回答

0

在調試器下的不同結果可能是因爲所有的數據套接字緩衝區配合,並從調試的額外延遲允許所有的數據之前到達致電Receive

然而,在正常執行情況下,情況並非如此。數據將以數據包形式到達,爲了知道數據的結束位置,您必須解析您的HTTP請求。套接字的Available屬性僅指示在緩衝區處有多少數據,它不是整個消息的長度。雖然這是絕對有可能使用原始套接字來讀,它更容易使用NetworkStream

IEnumerable<string> ReadRequestHeaders(Socket s) 
{ 
    using (var stream = new NetworkStream(s, false)) 
    using (var reader = new StreamReader(stream)) 
    { 
     while (true) 
     { 
      var line = reader.ReadLine(); 
      if (line == "") 
       break; 

      yield return line; 
     } 
    } 
} 

這同樣適用於HTTP消息的休息 - 爲了正確轉發它,你必須知道在哪裏它結束,這意味着理解Content-Length或Transfer-Encoding字段並相應地解析。