【问题标题】:My web server cannot find sub directories我的网络服务器找不到子目录
【发布时间】:2023-04-03 02:00:01
【问题描述】:

好的,很抱歉第一个问题是一个不好的问题。第二次尝试。 我使用 C# 和 System.Net 库创建了一个 Web 服务器(或响应程序?)。 这是服务器公共变量:

#region "Variables"
    private TcpListener _TcpListener;
    private Thread _ListenThread;
    private string _ServerDataPath = "";

    private string _Log = "[XMS LOG] Date : " + DateTime.Now.ToString("r") + "\r\n";

    public List<string> Defaults;
    public Dictionary<string, string> Mimes;
    #endregion

    private int _SendBufferSize = 2048;
    private int _ReceiveBufferSize = 2048;

    #region "Properties"
    public int SendBufferSize
    {
        get { return _SendBufferSize; }
        set
        {
            if (value <= 0)
            {
                return;
            }
            _SendBufferSize = value;
        }
    }

    public int ReceiveBufferSize
    {
        get { return _ReceiveBufferSize; }
        set
        {
            if (value <= 0)
            {
                return;
            }
            _ReceiveBufferSize = value;
        }
    }

    public TcpListener Listener
    {
        get { return _TcpListener; }
    }

    public Thread ListenThread
    {
        get { return _ListenThread; }
    }

    public String Path
    {
        get { return _ServerDataPath; }
    }
    #endregion

这是我的监听方法中的代码:

private void Listen()
{
    Socket cur = null;
    try
    {
       // Infinite loop
       while(true)
       {
           // Accept incoming socket
           cur = _TcpListener.AcceptSocket();
           // Limit socket buffers
           cur.SendBufferSize = SendBufferSize; cur.ReceiveBufferSize = ReceiveBufferSize;
           // Get request
           byte[] Request = new byte[ReceiveBufferSize];
           int RequestSize = cur.Receive(Request);
           string RequestStr = Encoding.Default.GetString(Request);
           // Clients send empty requests filled with nulls
           // To prevent lag if request is empty then directly close stream
           if (string.IsNullOrWhiteSpace(RequestStr) || string.IsNullOrEmpty(RequestStr))
           {
               cur.Close();
           }
           else
           {
               // Process request
               Process(cur, RequestStr);
               cur.Close();
           }
        }
    }
    catch (Exception ex)
    {
        SendError(cur, "TCPClient Listening Error", "500", "Runtime Exception", ex);
    }
}

此方法在线程上运行。这是我处理 http 请求的 Process 方法:

        private void Process(Socket skt, string Request)
        {
        try
        {
            // Split all the request from line terminators
            string[] RequestSplit = Request.Split(new string[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            // Get Request at top of this split array
            string GetRequest = RequestSplit[0];
            // Trim
            GetRequest = GetRequest.Trim();
            // Is it a get request?
            if (!GetRequest.StartsWith("GET"))
            {
                // Send error and return
                SendError(skt, "Bad Request : " + GetRequest, "400", "Bad Request");
                return;
            }
            // Split Get Request
            string[] GetRequestSplit = GetRequest.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
            // Is Request Legal?
            // Classical GET requests generally has 3 parts:
            // GET {FileName} HTTP/1.1
            // If we get length smaller than 3 then send error
            if (GetRequestSplit.Length < 3)
            {
                SendError(skt, "Bad Request : " + GetRequest, "400", "Bad Request");
                return;
            }
            Log(GetRequest);

            // As usual middle one is file
            string File = GetRequestSplit[1];
            // We patch server path directory to this file string
            File = _ServerDataPath + File;
            // Control if it is a directory
            // If it is a directory then control default files
            bool IsIndex = false;
            if (System.IO.Directory.Exists(File))
            {
                // This must be an index file
                IsIndex = true;
            }
            // Not index file? No problem
            // I just control that if there
            // Is a file called like that

            if (!IsIndex)
            {
                // Oops accidents happen.
                // Cannot find the file that you requested.
                if (!System.IO.File.Exists(File))
                {
                    SendError(skt, "Cannot find selected file", "404", "Not Found");
                    return;
                }
                // Ok we a legal file
                // Go out and send it!
            }
            // But if file is an index?
            // Simple, loop over every default file
            else
            {
                // No defaults defined by user?
                // Sorry, we do not serve index files.
                if (Defaults.Count == 0)
                {
                    SendError(skt, "Default files are not allowed", "404", "Not Found");
                    return;
                }

                for (int i = 0; i < Defaults.Count; i++)
                {
                    if (System.IO.File.Exists(File + "\\" + Defaults[i]))
                    {
                        // Get the index file. Patch it.
                        File += "\\" + Defaults[i];
                        goto send;
                    }
                }
                // Does not contain any default?
                // Send error again.
                SendError(skt, "Cannot find default file in requested directory", "404", "Not Fount");
                return;
            }
        send:
            // Here we are, sending data...
            // Byte buffer for sending
            byte[] Buffer = System.IO.File.ReadAllBytes(File);
            // Mime?
            string Mime = GetMime(File);
            // Directly send while it is hot already!
            SendMessage(skt, Buffer, true, "200", "OK", Mime);
        }
        catch (Exception ex)
        {
            SendError(skt, "Unknown exception", "500", "Internal Exception");
        }
    }

和我的发送消息方法:

        public void SendMessage(Socket skt, byte[] message, bool includeHeader = false, string statusCode = "200", string statusMessage = "OK", string mime = "text/plain")
    {
        if (skt == null) { return; }
        string header = "";
        if (includeHeader)
        {
            header = "HTTP/1.1 " + statusCode + " " + statusMessage + "\r\n";
            header += "Server: XMServer Module\r\n";
            header += "Date: " + DateTime.Now.ToString("r") + "\r\n";
            header += "Content-Type: " + mime + "; charset=utf-8\r\n";
            header += "Connection: Closed";
            header += "\r\n\r\n";
        }
        List<byte> buffer = Encoding.Default.GetBytes(header).ToList();
        buffer.AddRange(message);
        skt.Send(buffer.ToArray());
    }

我认为 SendError、GetMime 或 StrIsFile 方法没有问题,所以我不把它们放在这里。 这是一个名为 XMServer 的类。这是我的开始代码:

XMServer server = new XMServer(8080, "..\\web\\", 4096, 1024);
server.Mimes = MIMES;
server.Defaults = DEFAULTS;
server.Start();

问题是,服务器目录定义为 ..\web\ 我在那里放了一个 index.html 文件并在浏览器中输入 127.0.0.1:8080 并且服务器发送 index.html 页面。这很好,也是我想要实现的。我在“web”文件夹中创建了一个名为“docs”的文件夹,并在“docs”文件夹中放置了一个“images”文件夹。并将 index.html 文件放在“docs”文件夹中。 index.html 内容:

<html>
    <head>
        <title> Documentation </title>
        <meta charset="utf-8"/>
    </head>
    <body>
        <!-- This is where error pops out -->
        <img src="images/logo.png"/>
    </body>
</html>

服务器正确发送 index.html 文件。但是页面向服务器发送了一个请求,例如“GET /images/logo.png HTTP/1.1”(只是一个例子。我不确定请求是否完全等于这个)。服务器尝试发送“..\web\images\logo.png”,而不是“..\web\docs\images\logo.png”并将错误记录到文件中(我创建了一个方法来执行此操作)。当我们尝试在 web 文件夹的子目录中提供另一个 html 文件的链接时,也会发生同样的事情。我怎么能打败这个?而且我确信我的代码效率低下,请告诉我我的错误。任何帮助将不胜感激。

【问题讨论】:

  • 发帖前请阅读如何写出好问题的指南
  • 欢迎来到 Stack Overflow!我发现你的问题不是很清楚......请记住要清晰彻底,并包含示例(如果可能且合适)。请分享一些代码,以便我们在帮助您时有一些事情要做。 -- 适合新成员阅读的内容是How to askTour

标签: c#-4.0 request webserver tcplistener file-not-found


【解决方案1】:

成功了。我使用 HttpListener 而不是 TCPListener。目前服务器运行良好,也可以预处理 PHP 文件。

【讨论】:

    最近更新 更多