English 中文(简体)
C# Web 服务器连接问题
原标题:
  • 时间:2008-10-26 20:56:55
  •  标签:

我正在尝试制作一个简单的C#网页服务器,目前您可以通过浏览器访问并只会显示“Hello World”。

我遇到的问题是,服务器可以正常接收数据 - 我可以获取浏览器的头部信息 - 但浏览器收不到我发送的任何内容。此外,我只能通过访问本地主机 (或 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
"
                    + "Server: Test Server
"
                    + "Content-Type: text/html; "
                        + "charset=UTF-8
"
                    + "Content-Length: " + msg.Length + "
"
                    + "Date: Sun, 10 Aug 2008 22:59:59 GMT"
                        + "
";
            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);
    }
}

有人有任何想法吗?感觉好像是我自己的愚蠢,但我不知道是什么。我真的很感激任何的见解。

最佳回答

你可能会喜欢知道,你可以使用HttpListener轻松编写基本的Web服务器 - 这处理了大部分痛苦的部分,让你可以专注于编写实际的代码。MSDN页面提供了一个示例。

请注意,这使用HTTP.SYS,这是很好的 - 但意味着非管理员需要明确获得打开端口的访问权限; 在XP上,您可以使用httpcfg来操作此功能; 在vista上,您可以使用netsh。 请参见此处获取更多信息。

问题回答

目前不是问题,但以后可能会成为问题的一件事是,您的内容长度基于消息字符串的Unicode长度,而不是二进制长度。

连接构造函数中还有相当多的事情要处理-在我看来,这些东西确实不属于构造函数。如果出现异常,它也不会关闭事物。

你看过WireShark这样的网络追踪器中正在发生的事情吗?这将是最简单的方法,以查看是否向客户端发送了任何数据。

或者,您可以发布一份短小但完整的代码版本,以便我们可以编译和运行。

也许我只是漏了什么,但你只能在本地主机上连接的原因是因为你正在监听的IP是127.0.0.1,这会使TCPListener只在该IP地址上进行监听。我没有看到你在任何地方调用任何客户端断开连接的方法,TCPListener是一个阻塞调用,所以它会一直坐在那里,直到有连接被建立。根据我以往对TCP/IP和TCPListener、TCPClient类的经验,没有太多的方法可以强制监听器放弃它的连接,除非你放弃客户端连接。调用TCPListener.Abort()不会中断客户端连接,这会导致端口被堵塞。

对于局域网中想要从本地网络IP地址访问C#服务器的任何人来说,您需要侦听地址0.0.0.0,这意味着侦听所有IP地址,而不是特定的IP地址,如127.0.0.1等。





相关问题
热门标签