通过数据流接收C#中的数据并通过boost:asio http服务器示例读取数据

时间:2013-12-13 23:10:10

标签: c# c++ stream boost-asio webrequest

所以我的问题是我有一个文件,我想发布到我的boost:asio http服务器。客户端应用程序位于C#中。所以我尝试根据这里的很多帖子,甚至是微软自己的网站,做到以下几点。

string fileToSendServer = "Contains lots of data that needs to be written to file";
byte[] byteArray = UTF8Encoding.UTF8.GetBytes(fileToSendServer);

// Create a request using a URL that can receive a post. 
request = WebRequest.Create(destination);

// Set the Method property of the request to POST.
request.Method = "POST";
// Set the ContentType property of the WebRequest.
request.ContentType = "application/octet-stream";

// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
using (dataStream = request.GetRequestStream())
{
    // Write the data to the request stream.
    dataStream.Write(byteArray, 0, byteArray.Length);
    dataStream.Flush();
    // Close the Stream object.
    dataStream.Close();
}

客户端一直到GetRequestStream(),这似乎将标头发送到等待服务器。服务器处理标头,永远不会从Write()接收字节。

我曾尝试使用Fiddler2来观看数据包但我的IT已经锁定了我的机器,因此我无法运行Fiddler。

当我单步执行客户端的代码时,将执行所有代码行。当我在服务器上单步执行时,只在流上找到标题。

需要发送的数据是由客户端生成的,而不是真正的文件,直到它应该被写入服务器端的文件。该服务器类似于boost::asio http示例服务器之一。所以我不知道它是客户端还是服务器。我已经通过代码解析输入输入,并且从未接收过数据。所以我查看了连接,据我所知,传入的数据没有阻塞。

编辑: 好的,基于答案(包括我自己的答案),我取得了一些重大进展。问题的一半是在发送之前c#没有读取所有内容。现在C#Client正在读取和发送数据。客户端报告send命令发送了所有字节。但boost:asio http server 3仍未收到所有数据。问题是我使用的是示例http服务器,request module似乎没有捕获所有数据。它一次读取一个字节,似乎死于0x1f48字节的内容。

template <typename InputIterator>
boost::tuple<boost::tribool, InputIterator> parse(request& req,
    InputIterator begin, InputIterator end)
{
    while (begin != end)
    {
        boost::tribool result = consume(req, *begin++);
        if (result || !result)
        {
            return boost::make_tuple(result, begin);
        }
    }
    boost::tribool result = boost::indeterminate;
    if(state_ == getting_content) {
        result = boost::indeterminate;
    }
    return boost::make_tuple(result, begin);
}

当从请求中仅读取8008个字节时,begin ==结束。

2 个答案:

答案 0 :(得分:1)

(此答案基于您在当前接受的答案中提供的新信息)

实现Stream的所有Read类只需要读取 最多 传入计数的字节数。这就是它返回int的全部原因。

另外,由于Read没有为其参数设置long,如果返回的内容大于Int32.MaxLength,您仍会遗漏数据。

执行此操作的正确方法是读入较小的缓冲区,并将该缓冲区复制到较大的数组中。

byte[] data = new byte[response.ContentLength];
byte[] buffer = new byte[4 << 10]; //4k buffer, you can tweak it if you need to
long offset = 0;
int read;
do
{
    read = dataStream.Read(buffer, 0, buffer.Length);
    Array.Copy(buffer, 0, data, offset, read);
    offset += read;
} while (read > 0);

我不知道List<byte> content的用途,如果您要将data移至content,请注意response.ContentLength可能会遇到一些问题}大于Int32.MaxLength,因为没有成员可以使用索引或通过long而不是int获取长度。

答案 1 :(得分:0)

显然,response.GetResponseStream()会返回Stream,但不会Read()整个回复。为了解决这个问题,我不得不在响应中建立以下内容:

byte[] data = new byte[response.ContentLength];
int offset = 0;
while (offset < response.ContentLength)
{
    offset += dataStream.Read(data, offset, (int)(response.ContentLength - offset));
}
List<byte> content = new List<byte>(2 * (int)response.ContentLength);

然后,我能够通过第二个流写出来,最后确实收到了所有已发送的内容。每次在此更改之前检查文件输出时,该文件都包含内容中的内容。因此,似乎整个问题都是基于初始响应而不是“读取”发送的所有数据。

修改

此外,进入服务器的数据尚未完成。 boost:asio http示例代码存在捕获所有内容数据的问题。我只会收到一部分传入的内容或文件数据。它似乎每次都停在8008字节。我发现解析函数不正确。所以我修改了它:

        template <typename InputIterator>
        boost::tuple<boost::tribool, InputIterator> parse(request& req,
            InputIterator begin, InputIterator end)
        {
            //may have to handle multipart here.
            while (begin != end)
            {
                boost::tribool result = consume(req, *begin++);
                if (result || !result)
                {
                    return boost::make_tuple(result, begin);
                }
            }
            boost::tribool result = boost::indeterminate;
            if(state_ == getting_content) {
                if(req.content.length() < content_length_) {
                    result = boost::indeterminate;
                } else {
                    result = true;//boost::indeterminate;
                }
            }
            return boost::make_tuple(result, begin);
        }

最重要的是检查content长度并返回indeterminate此功能。然后确保connection的代码更多read_some,示例代码确实具有此代码。