所以我的问题是我有一个文件,我想发布到我的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 ==结束。
答案 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
,示例代码确实具有此代码。