问题
I'm creating simple proxy server but I faced a strange situation, I've following code :
var clientRequestStream = _tcpClient.GetStream();
var requestHeader = clientRequestStream.GetUtf8String();
GetUtf8String is a extension method for Stream class which reads stream (contains HttpRequest headers). I need to extract those headers to access Host and Requested Url. Once reading NetworkStream is done. I need to perform seek operation and set its clientRequestStream.Position = 0; because I've to read that stream and write it on another remote NetworkStream.
I don't know how should I solve this problem.Any advice will be helpful.
Edit: I also tried copy NetworkStream to MemoryStream then perform seek operation on MemoryStream, There is no exception but when I want to read from NetworkStream its buffer always is always empty.
Also I used reflector to see what happens inside Stream.CopyTo. See below code :
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);
}
}
This is what CopyTo doing. Even if I use CopyTo Problem is still unresolved. Because it reads source (Here NetworkStream) to the end. I there another way to handle this situation?
回答1:
Are you reading from this stream until the end? If so, I suggest you just copy the entire contents into a MemoryStream, then you can seek on that to your heart's content. In .NET 4 it's particularly easy with Stream.CopyTo:
MemoryStream dataCopy = new MemoryStream();
using (var clientRequestStream = _tcpClient.GetStream())
{
clientRequestStream.CopyTo(dataCopy);
}
dataCopy.Position = 0;
var requestHeader = dataCopy.GetUtf8String();
It makes sense for NetworkStream not to be seekable - it's just a stream of data that a server is giving to you. Unless you can tell the server to rewind (which only even makes sense in some situations) there's no way of seeking unless something buffers as much data as you need to rewind - which is basically what copying to a MemoryStream does, in a pretty brute-force fashion.
回答2:
As you've discovered, NetworkStream is not seekable.NetworkStream feeds you data directly from the network.
You should read the data into a MemoryStream and re-use that.
回答3:
Assuming you don't want to properly rewrite your GetUtf8String method to not require seek...
The easiest approach would be to copy stream to MemoryStream first and than you have stream you can seek as much as you want. Stream.CopyTo will take care of copying (.Net4+)
Note that you need to seek resulting MemoryStream back by setting Position property to 0 (copiedStream.Position=0) or cloning the stream by creating new one (preferably read only) based on buffer and length of first memory stream.
回答4:
You won't be able to set clientRequestStream.Position = 0 because NetworkStream is forward-only. See here: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.position.aspx
Be careful about thinking of NetworkStream in the same way as regular streams. Things like Peek() for example on a StreamReader can cause your application to block.
来源:https://stackoverflow.com/questions/11749036/networkstream-doesnt-support-seek-operations