3

I've following code:

_clientRequestStream = _tcpClient.GetStream();

var memoryStream = new MemoryStream();
_clientRequestStream.CopyTo(memoryStream);

CopyTo takes long long long time to copy a Stream into another Stream. It seems application stops there without any reason or at least I couldn't find the reason.

slavoo
  • 5,798
  • 64
  • 37
  • 39
Saber Amani
  • 6,409
  • 12
  • 53
  • 88
  • 3
    Maybe because the source stream is still open and waiting for more data?? – mellamokb Jul 31 '12 at 21:47
  • @mellamokb: Well how should I know that ? – Saber Amani Jul 31 '12 at 21:48
  • Certainly this is not the fault of CopyTo! The source stream is not delivering data. Probably the TCP server is not closing the connection. – usr Jul 31 '12 at 21:48
  • @usr: When I read NetworkStream directly it contains data. – Saber Amani Jul 31 '12 at 21:49
  • @SaberAmani, sure but it never ends (right?). – usr Jul 31 '12 at 21:50
  • @usr: No it ends when read all buffer. – Saber Amani Jul 31 '12 at 21:52
  • When you're reading it, you're reading just what's currently available, but there may be more in the future. `CopyTo` copies until _all_ of the data has been copied, which occurs only when the stream has been closed at the other end. – MRAB Jul 31 '12 at 21:56
  • @MRAB: well the problem is here, I don't know how should I know the stream is closed or not. – Saber Amani Jul 31 '12 at 21:58
  • @SaberAmani, I don't think you're right. You'd need to post some code so I can look at it. Maybe you mean, a single read ends? That might well be true, but you haven't depleted the stream yet. – usr Jul 31 '12 at 22:11
  • 1
    Sorry, but I'm curious why this question got -2 down votes ? I faced this problem and I want to solve it. Is there anything strange here ? – Saber Amani Jul 31 '12 at 22:14
  • @SaberAmani I'm not a -1 but I suspect it's the title (infinite days? prove it) and also the suggestion that that it's the technology at fault – Basic Jul 31 '12 at 22:20
  • @SaberAmani Think of it as if you were writing a chat program. You connect using TcpClient and get a NetworkStream when you enter a chat room. Then you can type in something and write it to the network stream and read chats from others from the network stream. When does that stream "end"? It stays open until one end closes it. CopyTo() does not just read AVAILABLE data, it reads to the END of the stream. – Jason Goemaat Jul 31 '12 at 22:33
  • Can I just say, if you did a HTTP request here, then make sure you are using `"Connection: Close"` and not `"Connection: Keep-Alive"` in your request – Worthy7 May 11 '18 at 01:35

3 Answers3

13

A network stream remains open until it is closed by one end of the stream. CopyTo() copies all data from the stream, waiting until the stream ends. If the server is not sending data, the stream does not end or close and CopyTo() dutifully waits for more data or for the stream to end. The server on the other end of the stream must close the stream for it to end and CopyTo() to return.

Google "TcpClient Tutorial" or "TcpCLient Sample" to get some good pages showing other ways you might use them, such as checking NetworkStream.DataAvailable to see if there is data waiting or if the stream is still open with no data. To just read some data and not wait for the stream to close you would use NetworkStream.Read() or wrap it in a StreamReader and use ReadLine(). It all depends on the server you are connecting to and what you are trying to accomplish.

Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113
  • I think CopyTo() would return when it is closed, a tutorial on asynchronous network processing is way outside the scope of the question. – Jason Goemaat Jul 31 '12 at 21:55
  • 1
    Jason is right: The only way to be sure that all data is received is either by the nature of the content (length-prefix) or by waiting for the stream to be closed. **How else could it possibly be?** TCP provides a stream. – usr Jul 31 '12 at 22:07
  • Thanks Jason at least I got some vision and start thinking how should I solve it. – Saber Amani Jul 31 '12 at 22:41
  • @SaberAmani It would really help to know what kind of server program you are connected to and the data you are expecting. – Jason Goemaat Jul 31 '12 at 22:50
  • It's a simple proxy server which I'm TRY to write it. Interesting point is here Jason, The DataAvailable property is always true. I check it inside a thread. but It always true. – Saber Amani Jul 31 '12 at 23:01
  • What does Length say? If you read all the data in a loop while DataAvailable is true, does it ever return false? How much data is being returned from your server? – Jason Goemaat Aug 02 '12 at 20:36
6

TCP is a stream protocol. Bytes can flow at an arbitrary rate. Theoretically you could get one byte, then several seconds later 10 bytes, then several minutes later two bytes.

TCP is useless as a protocol in and of itself.

There must be a higher-order protocol whose structure allows for the detection of both the beginning and the end of a "message". We cannot guess at what higher-order protocol you are listening to, you have to know that in order to listen.

Tergiver
  • 14,171
  • 3
  • 41
  • 68
2

This will block indefinitely I believe until the underlying connection is closed, in which case I assume it would throw an IOException. Be careful with thinking of NetworkStream like a normal Stream. TCPClient.GetStream() is a nice abstraction which saves you the hassle of using Socket directly, but it's easy to fall into traps like these using synchronous operations with NetworkStream. It's worth checking out the specific MSDN documentation on NetworkStream.

Here's a nice example of using async sockets as opposed to TCP client: http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

Cashley
  • 516
  • 5
  • 16
  • async sockets are no help here. The problem remains: How to detect when the stream ends. – usr Jul 31 '12 at 22:12
  • As Terdiver says above, TCP only guarantees byte order and not how many bytes you will receive, which is why you often run into issues once you start testing in a non-local environment. If you have any control over the protocol sitting on top of this it's good practice to build a buffer until ready and rely on a framing mechanism for the 'message' (sometimes as simple as a newline) – Cashley Jul 31 '12 at 22:14