2008-10-26 2 views
1

Я пытаюсь создать простой веб-сервер C#, который на данном этапе может получить доступ через ваш браузер и просто сделает «Hello World».Проблема подключения к веб-серверу C#

Проблема, с которой я столкнулась, заключается в том, что сервер может получать данные в порядке - я получаю информацию заголовка браузера, но браузер не получает ничего, что я отправляю. Кроме того, я могу подключиться только к серверу, перейдя на 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 для простого создания базового веб-сервера - это касается большинства болезненных битов, позволяя вам сосредоточиться на написании фактического кода. Пример страницы 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() не отключает клиентское соединение, которое блокирует блокировку порта.

Смежные вопросы