简单C#HTTP服务器上的内容长度偶尔出错
本文关键字:偶尔 出错 C#HTTP 服务器 简单 | 更新日期: 2023-09-27 18:06:48
对于一些实验,在这里使用简单的HTTP服务器代码
在一个案例中,我希望它提供一些ANSI编码的文本配置文件。我知道这个代码还有更多的问题,但我目前唯一关心的是内容长度是错误的,但仅适用于某些文本文件。
示例代码:
输出流初始化:
outputStream = new StreamWriter(new BufferedStream(socket.GetStream()));
HTTP获取的处理:
public override void handleGETRequest(HttpProcessor p)
{
if (p.http_url.EndsWith(".pac"))
{
string filename = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), p.http_url.Substring(1));
Console.WriteLine(string.Format("HTTP request for : {0}", filename));
if (File.Exists(filename))
{
FileInfo fi = new FileInfo(filename);
DateTime lastWrite = fi.LastWriteTime;
Stream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
StreamReader sr = new StreamReader(fs);
string result = sr.ReadToEnd().Trim();
Console.WriteLine(fi.Length);
Console.WriteLine(result.Length);
p.writeSuccess("application/x-javascript-config",result.Length,lastWrite);
p.outputStream.Write(result);
// fs.CopyTo(p.outputStream.BaseStream);
p.outputStream.BaseStream.Flush();
fs.Close();
}
else
{
Console.WriteLine("404 - FILE not found!");
p.writeFailure();
}
}
}
public void writeSuccess(string content_type,long length,DateTime lastModified) {
outputStream.Write("HTTP/1.0 200 OK'r'n");
outputStream.Write("Content-Type: " + content_type + "'r'n");
outputStream.Write("Last-Modified: {0}'r'n", lastModified.ToUniversalTime().ToString("r"));
outputStream.Write("Accept-Range: bytes'r'n");
outputStream.Write("Server: FlakyHTTPServer/1.3'r'n");
outputStream.Write("Date: {0}'r'n", DateTime.Now.ToUniversalTime().ToString("r"));
outputStream.Write(string.Format("Content-Length: {0}'r'n'r'n", length));
}
对于我测试过的大多数文件来说,内容长度是正确的。然而,当使用HTTP调试工具Fiddler进行测试时,有时会在Content-Length上报告违反协议的情况。
例如fiddler说:
请求计数:1发送的字节数:303(标头:303;正文:0(接收的字节数:29847(标头:224;正文:29623(
因此内容长度应为29623。但是生成的HTTP头是
Content-Length: 29617
我保存了Fiddler的HTTP内容,并明显地比较了文件,没有注意到任何差异。然后将它们加载到BeyondCompare Hex compare中,这样的文件有几个问题:
Original File: 2D 2D 96 20 2A 2F
HTTP Content : 2D 2D EF BF BD 20 2A 2F
Original File: 27 3B 0D 0A 09 7D 0D 0A 0D 0A 09
HTTP Content : 27 3B 0A 09 7D 0A 0A 09
我怀疑这个问题和编码有关,但不完全确定。只提供ANSI编码的文件,不提供Unicode。
我通过用字节序列修改文件的部分内容,使文件的内容长度正确。在文件的三个部分中进行了更改:
2D 2D 96 (--–) to 2D 2D 2D (---)
根据粘贴的字节数,这里似乎出现了一些问题。首先,您的输入文件(0D 0A(中的CRLF似乎正在被转换为LF(0A(。其次,当将文件读取到string
或Write
将字符串发送到HTTP客户端时,字符编码似乎正在发生变化。
HTTP内容长度表示流中的字节数,而字符串。长度提供字符串中的字符数。除非您的文件只使用前128个ASCII字符(这排除了非英语字符以及特殊的windows-1252字符,如欧元符号(,否则该字符串不太可能出现。长度将完全等于UTF-8或ISO-8859-1编码的字符串的长度。
如果在将字符串发送到客户端之前将其转换为byte[]
,则可以获得"true"内容长度。然而,如果你没有使用正确的编码读取文件,你仍然会收到混乱的文本。(无论是否指定编码,在将文件读取为Unicode字符的string
时都会发生转换。(
我强烈建议在Content-Type标头中指定字符集(例如application/x-javascript-config;charset=utf-8
(。不管您的字符集是utf-8、utf-16、iso-8859-1、windows-1251等,只要它与您将字符串转换为字节[]时使用的字符编码相同即可。