简单C#HTTP服务器上的内容长度有时会出错

简单C#HTTP服务器上的内容长度有时会出错,c#,http,character-encoding,fiddler,C#,Http,Character Encoding,Fiddler,在一些实验中,我们使用的是简单的HTTP服务器代码 在一个例子中,我希望它能够提供一些ANSI编码的文本配置文件。我知道这段代码有更多的问题,但我目前唯一关心的是内容长度是错误的,但只适用于某些文本文件 示例代码: 输出流初始化: outputStream = new StreamWriter(new BufferedStream(socket.GetStream())); HTTP get的处理: public override void handleGETRequest(HttpProce

在一些实验中,我们使用的是简单的HTTP服务器代码

在一个例子中,我希望它能够提供一些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));   
              }
对于我测试过的大多数文件,内容长度都是正确的。但是,在使用HTTP调试工具进行测试时,有时会在内容长度上报告协议冲突

例如,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

我用字节序列修改了文件的部分内容,使文件的内容长度正确。在文件的3个部分中进行了此更改:

2D 2D 96 (--–) to 2D 2D 2D (---)

根据您粘贴的字节数,这里似乎出现了一些问题。首先,您的输入文件(0D 0A)中的CRLF似乎正在转换为LF(0A)。其次,在将文件读入
字符串
将字符串写入HTTP客户端时,字符编码似乎正在改变

HTTP内容长度表示流中的字节数,而string.Length表示字符串中的字符数。除非您的文件仅使用前128个ASCII字符(这排除了非英语字符以及特殊的windows-1252字符,如欧元符号),否则string.Length不太可能完全等于UTF-8或ISO-8859-1中编码的字符串的长度

如果在将字符串发送到客户端之前将其转换为
字节[]
,则可以获得“true”内容长度。但是,如果您没有使用正确的编码读取文件,最终仍然会导致文本损坏。(无论是否指定编码,将文件读入Unicode字符的
字符串时都会发生转换。)


我强烈建议在内容类型头中指定字符集(例如
application/x-javascript-config;charset=utf-8
)。不管您的字符集是utf-8、utf-16、iso-8859-1、windows-1251等,只要它是您在将字符串转换为字节[]时使用的相同字符编码。

根据您粘贴的字节,这里似乎有一些问题。首先,您的输入文件(0D 0A)中的CRLF似乎正在转换为LF(0A)。其次,在将文件读入
字符串
将字符串写入HTTP客户端时,字符编码似乎正在改变

HTTP内容长度表示流中的字节数,而string.Length表示字符串中的字符数。除非您的文件仅使用前128个ASCII字符(这排除了非英语字符以及特殊的windows-1252字符,如欧元符号),否则string.Length不太可能完全等于UTF-8或ISO-8859-1中编码的字符串的长度

如果在将字符串发送到客户端之前将其转换为
字节[]
,则可以获得“true”内容长度。但是,如果您没有使用正确的编码读取文件,最终仍然会导致文本损坏。(无论是否指定编码,将文件读入Unicode字符的
字符串时都会发生转换。)


我强烈建议在内容类型头中指定字符集(例如
application/x-javascript-config;charset=utf-8
)。您的字符集是否为utf-8、utf-16、iso-8859-1、windows-1251等并不重要,只要它与您在将字符串转换为字节[]时使用的字符编码相同即可.

我想向我的客户端发送字节数组,但由于某种原因,当我使用outputstream.BaseStream.Write时,内容与客户端的顺序不符,即我的一半头在内容的末尾,一半头在开头。但是,由于我现在只提供ASCII编码的文件,所以将代码更改为这个固定问题:byte[]data=File.ReadAllBytes(filename);p、 writeSuccess(“应用程序/x-javascript-config”,data.Length,lastWrite);p、 Write(System.Text.Encoding.ASCII.GetString(数据));我想向我的客户端发送字节数组,但由于某种原因,当我使用outputstream.BaseStream.Write时,内容与我的客户端的顺序不符,即我的一半头在内容的末尾,一半头在开头。但是,由于我现在只提供ASCII编码的文件,所以将代码更改为这个固定问题:byte[]data=File.ReadAllBytes(filename);p、 writeSuccess(“应用程序/x-javascript-config”,data.Length,lastWrite);p、 Write(System.Text.Encoding.ASCII.GetString(数据));