0

My program implementing http client (by inheriting from TCPClient) which sends requests to http server in order to get chunk transfer encoding streaming (in other words, video stream over HTTP).

In order to monitor connection between client and server I started background thread that trying to write null byte (0x00) to the same socket and discover connection problems accordingly (as recommended here):

while (Client != null && Client.Send(ping) > 0)
    Thread.Sleep(2000);

The impact of writing from two threads is that in Wire-shark sometimes I see that ping and the HTTP request in the same packet, like this:

00 10 18 8d 23 ab 00 11 5d b9 e8 00 08 00 45 00  ....#...].....E.
00 b1 38 21 40 00 3e 06 77 de 0a 3f 03 3d 0a 3f  ..8!@.>.w..?.=.?
74 8d 89 7f 00 50 6b c3 45 a8 9f 76 4a 88 80 18  t....Pk.E..vJ...
13 5d a9 ad 00 00 01 01 08 0a 9c ea b6 a5 00 06  .]..............
9f 8b 47 45 54 20 2f 73 74 72 65 61 6d 2f 31 2f  ..GET /stream/1/
45 76 65 6e 74 41 20 48 54 54 50 2f 31 2e 31 0d  EventA HTTP/1.1.

And of course the server ignore this packet and can't see the http request.

Is there any way to write to socket and using Send method and make sure it will be sent in ONE packet?

[EDIT]

As I can understand from David and TAS's answers - that is not possible. And this is not even how TCP meant to operate.

Community
  • 1
  • 1
uriel
  • 1,209
  • 1
  • 16
  • 26
  • 4
    That's just not how TCP works. TCP is a byte-stream protocol that does not preserve application-level message boundaries. – David Schwartz Oct 27 '13 at 14:05
  • So server should know how to handle this or what? – uriel Oct 27 '13 at 14:09
  • 1
    How to handle what? Random junk being inserted into the data stream? It's not clear what the basis for your question is. You say "The problem is", but never explain what the symptoms of the problem are or why you think there's a problem at all. – David Schwartz Oct 27 '13 at 14:12
  • The server will know the size of a packet by inspecting the headers and should treat the data within these boundaries as one packet. – Jeroen Vannevel Oct 27 '13 at 14:13
  • 1
    @JeroenVannevel you might want that, but it doesn't work that way. For good reasons: packet sizes are limited, and performance optimizations are possible by coalescing packets. – usr Oct 27 '13 at 14:19
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Oct 27 '13 at 15:04

2 Answers2

1

Don't monitor the connection. Just try to use it and see if you succeed or fail. Trust me, what you're trying to do will cause you nothing but pain. The other end will have no idea what to do with the zero bytes you are sending.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • This client intended to test the server. And if I'll assume it connected unless I'll get an exception when it tries to read (and will not use a monitor), I'll test nothing. – uriel Oct 27 '13 at 14:26
  • 1
    @uriel The key is that you will either get an exception when you try to *write* or the server will fail to respond to your request. You can't rely on getting exceptions when you read -- it's always possible nothing will happen. – David Schwartz Oct 27 '13 at 14:27
0

There is one problem with your approach: writing data to the web server like you are is violating HTTP and may cause the server to crash or drop your connection.

The client you are implementing will be continously reading data from the server. The calls to read will show if the server closed the connection or throw an exception if a timeout occurred. The latter will usually happen when there is some sort of network problem, as web servers close there connections gracefully.

Update: Pausing the transfer on client will not stop the server from continuing sending chunks. If the data is not received the underlying OS buffers will fill up and finally packets will be dropped. The end result may be that the server closes the connection because it believes that there are some problems with the network.

One solution is to continue reading chunks and store them in a buffer for later playback. If there isn't enough memory avaiable, then I would close the connection and reconnect when the user resumes.

TAS
  • 2,039
  • 12
  • 17
  • 1
    This is, unfortunately, not so. TCP does not guarantee that a connection close or error will be detected by a side that does not send data. – David Schwartz Oct 27 '13 at 14:13
  • Also, if I will rely on the read exception I'll not be informed that server disconnected while I'm not trying to read video chunks (for example on pause). – uriel Oct 27 '13 at 14:21
  • @DavidSchwartz Yes, but a reasonable way to detect an error in this scenario is to attempt to read from the socket. If the socket was closed using a FIN packet and that packet is recieved by the client, any future reads will show that. If there is some problem with the network then the read will time-out. And the application should treat that as an error and close the socket. – TAS Oct 27 '13 at 14:23
  • 2
    @uriel When you're not using the connection, you cannot tell if it's still working unless you send requests. If you really do need to know that the connection is still working, send some kind of harmless (but legal) HTTP request. – David Schwartz Oct 27 '13 at 14:28
  • @uriel Even if playback is paused, you should not stop reading from the server or the OS buffers will overfill and you may loose data. If the user pauses for a long time I think the nice thing to do for both your users (who may be on an expensive connection) and the server (which may have limited resources) is to close the connection. And try to reconnect when the user starts playback. Using data from a buffer will allow you to provide a smooth playback experience for the end user. – TAS Oct 27 '13 at 14:32