对于某些实验,使用简单HTTP服务器代码here
在一个案例中,我希望它能够提供一些ANSI编码的文本配置文件。我知道此代码存在更多问题,但我目前唯一关注的是内容长度错误,但仅适用于某些文本文件。
示例代码:
输出流初始化:
outputStream = new StreamWriter(new BufferedStream(socket.GetStream()));
处理HTTP get:
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));
}
对于我使用Content-Length测试的大多数文件都是正确的。但是,在使用HTTP调试工具Fiddler进行测试时,有时会在Content-Length上报告协议违规。
例如fiddler说:
请求数:1 发送的字节数:303(标题:303;正文:0) 收到的字节数:29,847(标题:224;正文:29,623)
所以Content-Length应该是29623.但生成的HTTP头是
Content-Length: 29617
我从Fiddler保存了HTTP内容的主体并且明显地比较了文件,无法发现任何差异。然后将它们加载到BeyondCompare Hex比较中,这样的文件有几个问题:
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。
通过使用字节序列修改文件的部分,我使用正确的Content-Length使文件正确服务。在文件的3个部分中进行了此更改:
2D 2D 96 (--–) to 2D 2D 2D (---)
答案 0 :(得分:4)
根据您粘贴的字节数,看起来这里有一些问题。首先,输入文件(0D 0A)中的CRLF似乎正在转换为LF(0A)。其次,看起来字符编码正在改变,无论是将文件读入string
,还是将Write
字符串写入HTTP客户端。
HTTP Content-Length表示流中的字节数,而string.Length表示字符串中的字符数。除非您的文件专门使用前128个ASCII字符(排除非英文字符以及特殊窗口-1252字符,如欧元符号),否则string.Length不太可能完全等于字符串的长度以UTF-8或ISO-8859-1编码。
如果您在将字符串发送到客户端之前将其转换为byte[]
,那么您将能够获得" true"内容长度。但是,如果您没有使用正确的编码读取文件,那么您仍然会遇到损坏的文本。 (无论您是否指定编码,在将文件读取为string
个Unicode字符时都会发生转换。)
我强烈建议在Content-Type标头中指定字符集(例如application/x-javascript-config;charset=utf-8
)。您的字符集是utf-8,utf-16,iso-8859-1,windows-1251等也无关紧要,只要它与转换字符串时使用的字符编码相同即可到一个字节[]。