2008-10-26 131 views
1

我試圖做一個簡單的C#web服務器,在這個階段,你可以通過瀏覽器訪問,只會做一個「Hello World」。C#Web服務器連接問題

我遇到的問題是服務器可以接收數據正常 - 我得到瀏覽器的頭信息 - 但瀏覽器沒有收到我發送的任何內容。此外,我只能通過轉到localhost(或127.0.0.1)連接到服務器。我不能通過去我的IP,它不是一個網絡設置,因爲Apache運行良好,如果我運行它。另外,我正在使用一個端口監視程序,並且在我嘗試從瀏覽器進行連接之後,即使我告訴連接關閉,進程的端口仍然處於TIME_WAIT狀態,應該返回到LISTEN狀態。

下面是相關的代碼。一對夫婦的電話可能沒有意義,但這是一個更大的計劃。

class ConnectionHandler 
{ 
    private Server server; 

    private TcpListener tcp; 

    private ArrayList connections; 

    private bool listening; 

    private Thread listeningThread; 

    public Server getServer() 
    { 
     return server; 
    } 

    private void log(String s, bool e) 
    { 
     server.log("Connection Manager: " + s, e); 
    } 

    private void threadedListen() 
    { 
     while (listening) 
     { 
      try 
      { 
       TcpClient t = tcp.AcceptTcpClient(); 
       Connection conn = new Connection(this, t); 
      } 
      catch (NullReferenceException) 
      { 
       log("unable to accept connections!", true); 
      } 
     } 
     log("Stopped listening", false); 
    } 

    public void listen() 
    { 
     log("Listening for new connections", false); 
     tcp.Start(); 
     listening = true; 
     if (listeningThread != null && listeningThread.IsAlive) 
     { 
      listeningThread.Abort(); 
     } 
     listeningThread = new Thread(new ThreadStart(
      this.threadedListen)); 
     listeningThread.Start(); 
    } 

    public void stop() 
    { 
     listening = false; 
     if (listeningThread != null) 
     { 
      listeningThread.Abort(); 
      log("Forced stop", false); 
     } 
     log("Stopped listening", false); 
    } 

    public ConnectionHandler(Server server) 
    { 
     this.server = server; 
     tcp = new TcpListener(new IPEndPoint(
      IPAddress.Parse("127.0.0.1"), 80)); 
     connections = new ArrayList(); 
    } 
} 

class Connection 
{ 
    private Socket socket; 
    private TcpClient tcp; 

    private ConnectionHandler ch; 

    public Connection(ConnectionHandler ch, TcpClient t) 
    { 
     try 
     { 
      this.ch = ch; 
      this.tcp = t; 
      ch.getServer().log("new tcp connection to " 
       + this.tcp.Client.RemoteEndPoint.ToString(), false); 
      NetworkStream ns = t.GetStream(); 

      String responseString; 
      Byte[] response; 
      Int32 bytes; 
      responseString = String.Empty; 
      response = new Byte[512]; 
      bytes = ns.Read(response, 0, response.Length); 
      responseString = 
       System.Text.Encoding.ASCII.GetString(response, 0, bytes); 
      ch.getServer().log("Received: " + responseString); 

      String msg = "<html>Hello World</html>"; 
      String fullMsg = "HTTP/1.x 200 OK\r\n" 
        + "Server: Test Server\r\n" 
        + "Content-Type: text/html; " 
         + "charset=UTF-8\r\n" 
        + "Content-Length: " + msg.Length + "\r\n" 
        + "Date: Sun, 10 Aug 2008 22:59:59 GMT" 
         + "\r\n"; 
      nsSend(fullMsg, ns); 
      nsSend(msg, ns); 

      ns.Close(); 
      tcp.Close(); 
     } 
     catch (ArgumentNullException e) 
     { 
      ch.getServer().log("connection error: argument null exception: " + e); 
     } 
     catch (SocketException e) 
     { 
      ch.getServer().log("connection error: socket exception: " + e); 
     } 
    } 

    private void nsSend(String s, NetworkStream ns) 
    { 
     Byte[] data = System.Text.Encoding.ASCII.GetBytes(s); 
     ns.Write(data, 0, data.Length); 
     ns.Flush(); 
     ch.getServer().log("Sent: " + s); 
    } 
} 

有沒有人有任何想法?這感覺就像我的一部分是愚蠢的,但我不知道是什麼。我真的很感激任何見解

回答

1

您可能想知道,您可以使用HttpListener輕鬆編寫基本的Web服務器 - 這可以處理大部分痛苦的事情,讓您專注於編寫實際的代碼。 MSDN頁面舉例說明。

請注意,這使用HTTP.SYS,這是很好 - 但意味着非管理員需要明確給予訪問打開的端口;在XP上,你可以用httpcfg來做到這一點;在Vista上,您可以使用netsh。有關更多信息,請參閱here

+0

那麼,如果你打算把所有的樂趣都拿出來......;) – 2008-10-26 21:17:30

1

有一兩件事,是不是現在的一個問題,但可能以後是你的內容長度是基於Unicode的長度消息字符串的,而不是二進制長度。

在Connection構造函數中還有很多東西 - 實際上根本不屬於構造函數的東西,IMO。如果發生異常,它也不會結束。

你看過像WireShark這樣的網絡追蹤器發生了什麼嗎?這將是查看是否有任何數據被髮送回客戶端的最簡單方法。

或者,發佈一段簡短但完整的代碼,我們可以編譯和運行自己的代碼。

0

也許我只是錯過了一些東西,但你只能在本地主機上連接的原因是你正在監聽的IP是127.0.0.1,這使得TCPListener只能監聽該IP地址。而且我沒有看到任何你調用任何客戶端斷開連接的地方,TCPListener是一個阻塞呼叫,所以它永遠坐在那裏,直到連接完成。在我以前使用TCP/IP和TCPListener的經驗中,TCPClient類沒有太多方法強制偵聽器放棄連接,直到刪除客戶端連接。調用TCPListener.Abort()不會丟棄阻止端口阻塞的客戶端連接。