【问题标题】:Weird behavior: TcpListener奇怪的行为:TcpListener
【发布时间】:2010-08-09 03:01:55
【问题描述】:

所以,对于一些背景知识: 创建此类以接受和响应以 HTTP 格式远程发出的调用。

问题是当请求的方法是 POST 时,有时请求被正确处理,但大多数时候类最终只是没有响应。 此外,即使请求被正确处理,“Debug1”和“Debug2”行也永远不会写入控制台。 只有正确处理请求时才会出现“Debug3”行。

我知道这可能看起来很乱,C# 对我来说只是一个爱好,我正在学习 :) 感谢您花时间浏览此代码!

代码如下:

class WebServer
{
    private TcpListener myListener;

    public WebServer(int port)
    {
        //Threading the listener
        try
        {
            myListener = new TcpListener(IPAddress.Any, port) ;
            myListener.Start();

            Thread th = new Thread(new ThreadStart(StartListen));
            th.Start() ;
        }
        catch(Exception e)
        {
            Logs.Add("WebServer|An Exception Occurred while Listening :" +e.ToString());
        }
    }
    private void StartListen()
    {
        int iStartPos = 0;
        string sHttpVersion;
        string sResponse = "";
        string sCode = " 200 OK";

        while(true)
        {
            //Accept a new connection
            Socket mySocket = myListener.AcceptSocket();
            if(mySocket.Connected)
            {
                Byte[] bReceive = new Byte[1024];
                int i = mySocket.Receive(bReceive,bReceive.Length,SocketFlags.None);
                string sBuffer = Encoding.ASCII.GetString(bReceive).TrimEnd('\0');

                iStartPos = sBuffer.IndexOf("HTTP",1);
                sHttpVersion = sBuffer.Substring(iStartPos,8); //http version (ex: "HTTP/1.1")

                if (sBuffer.StartsWith("GET / "))
                {
                    Logs.Add("WebServer|Connected:" + mySocket.RemoteEndPoint.ToString());
                    sResponse = ArrayToJson();
                }
                else if (sBuffer.StartsWith("POST"))
                {
                    Console.WriteLine("Debug1");

                    //This is a POST request, so more data is waiting to be retreived...  
                    bReceive = new Byte[2048];
                    i = mySocket.Receive(bReceive,bReceive.Length,SocketFlags.None);
                    sBuffer = Encoding.ASCII.GetString(bReceive).TrimEnd('\0');

                    Console.WriteLine("Debug2");

                    //Parsing the request
                    string[] sParams = sBuffer.Split(',');
                    Console.WriteLine(sParams.Length);
                    Console.WriteLine("Debug3: {0} - {1} - {2} - {3} - {4}", sParams[0], sParams[1], sParams[2], sParams[3], sParams[4]);

                    //I do what needs to be done here

                    Logs.Add("WebServer|BotStartRequest:" + mySocket.RemoteEndPoint.ToString());
                    sResponse = "Accepted";
                }

                //Sending response and closing socket
                SendHeader(sHttpVersion, "text/html", sResponse.Length, sCode, ref mySocket);
                SendToBrowser(sResponse, ref mySocket);
                mySocket.Close();
            }
        }
    }
}

}

【问题讨论】:

  • 您是否尝试过增大接收缓冲区的大小?如果浏览器发送 > 2048 字节,那么我希望您最终可能会遇到一种情况,即您只读取了请求的一部分,并且对话将处于“狡猾状态”。
  • 我怀疑这是问题所在,因为我从未见过该正文接近 2048 字节。我也只用几个不同的请求完成了我的测试,它们中的大多数都有完全相同的身体,它仍然只是随机工作......
  • 这是移植的 C++,而不是惯用的 C#,因此调试非常困难。您需要在 while 循环中使用 try/catch+log 才能开始弄清楚这一点。您处理缓冲区的方式效率低下,很可能是问题的根源。

标签: c# webserver tcplistener


【解决方案1】:

实施 HTTP/1.1 并不是一项简单的任务。基本协议看起来很简单,但即使是最小的服务器实现也很难正确实现:您至少要考虑持久连接,例如 Expect: 100-continue 标头的 POST ,正确解析标题等等。

我强烈建议您查看现有的库/代码。例如,HttpListener 类内置于 .NET Framework 中,可能已经提供了您所需要的一切。

如果您真的想从头开始实现服务器,请查看Microsoft Cassini,这是一个简单的 HTTP 服务器,用 C# 编写,获得 Ms-PL 许可。

【讨论】:

  • 谢谢,如果我不能让它工作,那可能就是我最终要做的。但正是因为我对它的使用非常简单,所以我想把它变成我自己的,而不是使用现有的库。
猜你喜欢
  • 2017-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2015-07-20
  • 2010-10-03
  • 2021-07-12
相关资源
最近更新 更多