1

我正在创建简单的代理服务器,但我遇到了一个奇怪的情况,我有以下代码:

var clientRequestStream = _tcpClient.GetStream();
var requestHeader = clientRequestStream.GetUtf8String();

GetUtf8StringStream是读取流(包含HttpRequest标题)的类的扩展方法。我需要提取这些标头以访问 Host 和 Requested Url。一旦读取 NetworkStream 完成。我需要执行 seek 操作并设置它clientRequestStream.Position = 0;,因为我必须读取该流并将其写入另一个 remote NetworkStream

我不知道我应该如何解决这个问题。任何建议都会有所帮助。


编辑:我也尝试将 NetworkStream 复制到 MemoryStream 然后对 MemoryStream 执行查找操作,没有例外,但是当我想从 NetworkStream 读取时,它的缓冲区总是空的。

我也用反射器看看里面发生了什么Stream.CopyTo。见下面的代码:

    private void InternalCopyTo(Stream destination, int bufferSize)
    {
        int num;
        byte[] buffer = new byte[bufferSize];
        while ((num = this.Read(buffer, 0, buffer.Length)) != 0)
        {
            destination.Write(buffer, 0, num);
        }
    }

这就是 CopyTo 所做的。即使我使用CopyTo问题仍然没有解决。因为它将源(Here NetworkStream)读取到最后。我有另一种方法来处理这种情况吗?

4

4 回答 4

6

你是从这个流中读到最后吗?如果是这样,我建议您将整个内容复制到一个MemoryStream中,然后您可以随心所欲地寻找。在 .NET 4 中,它特别容易Stream.CopyTo

MemoryStream dataCopy = new MemoryStream();
using (var clientRequestStream = _tcpClient.GetStream())
{
    clientRequestStream.CopyTo(dataCopy);
}
dataCopy.Position = 0;
var requestHeader = dataCopy.GetUtf8String();

不可搜索是有道理的NetworkStream——它只是服务器提供给您的数据流。除非您可以告诉服务器倒带(仅在某些情况下才有意义),否则没有办法寻找,除非某些东西缓冲了您需要倒带的尽可能多的数据 - 这基本上就是复制到 aMemoryStream所做的事情,非常蛮力时尚。

于 2012-07-31T21:12:40.203 回答
3

正如您所发现的,NetworkStream它是不可搜索的。
NetworkStream直接从网络为您提供数据。

您应该将数据读入 aMemoryStream并重新使用它。

于 2012-07-31T21:11:57.867 回答
1

假设您不想正确重写您的 GetUtf8String 方法以不需要搜索...

最简单的方法是首先将流复制到 MemoryStream ,然后你可以尽可能多地寻找流。Stream.CopyTo将负责复制(.Net4+)

请注意,您需要通过将 Position 属性设置为 0 ( copiedStream.Position=0) 或通过基于缓冲区和第一个内存流的长度创建新的(最好是只读的)来克隆流来寻找结果 MemoryStream。

于 2012-07-31T21:14:11.467 回答
0

您将无法设置 clientRequestStream.Position = 0 因为 NetworkStream 是只转发的。见这里:http: //msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.position.aspx

以与常规流相同的方式考虑 NetworkStream 时要小心。例如在 StreamReader 上的 Peek() 之类的东西可能会导致您的应用程序阻塞。

于 2012-07-31T21:15:46.773 回答