我的网络服务器找不到子目录
My web server cannot find sub directories
好的,抱歉第一个问题不好。第二次尝试。
我使用 C# 和 System.Net 库创建了一个 Web 服务器(或响应器?)。
这是服务器 public 变量:
#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 的 class。这是我的开始代码:
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" 文件夹。并在 "docs" 文件夹中放置一个 index.html 文件。 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”并将错误记录到文件(我创建了一个方法来执行此操作)。当我们尝试将 link 赋给 Web 文件夹子目录中的另一个 html 文件时,也会发生同样的事情。我怎么能打败这个?而且我确信我的代码效率低下,请告诉我我的错误。任何帮助将不胜感激。
搞定了。我使用了 HttpListener 而不是 TCPListener。目前服务器运行良好,也可以预处理 PHP 个文件。
好的,抱歉第一个问题不好。第二次尝试。 我使用 C# 和 System.Net 库创建了一个 Web 服务器(或响应器?)。 这是服务器 public 变量:
#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 的 class。这是我的开始代码:
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" 文件夹。并在 "docs" 文件夹中放置一个 index.html 文件。 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”并将错误记录到文件(我创建了一个方法来执行此操作)。当我们尝试将 link 赋给 Web 文件夹子目录中的另一个 html 文件时,也会发生同样的事情。我怎么能打败这个?而且我确信我的代码效率低下,请告诉我我的错误。任何帮助将不胜感激。
搞定了。我使用了 HttpListener 而不是 TCPListener。目前服务器运行良好,也可以预处理 PHP 个文件。