11

I wanted to know how to flush the socket streams while doing socket programming in C. I tried all the options- setting TCP_NODELAY using the following code-

setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));      

Note: all the flag and sockfd are declared correctly.

I used this function both before send() and after send() but it did not make any difference.

Also someone had suggested to use shutdown() after each send() but that works only for one instance. When I use it to send some text again, it doesn't work- actually the connection gets closed after I use shutdown().

shutdown(sockfd, SHUT_WR);

Can someone help in this regard?

I wanted to added that- the server is a Java socket and the client is a C socket. The C socket implements the JVMTI interface and sends the information to the Java socket.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
MohamedSanaulla
  • 6,112
  • 5
  • 28
  • 45
  • 1
    You should mention which platform you are working on - Windows or *nix for clarity. – batbrat Jan 31 '10 at 11:15
  • Oh sorry for missing that- working on Linux, to be specific- Ubuntu 9.10 – MohamedSanaulla Jan 31 '10 at 11:16
  • Can you post more of your code? Are you checking the return value from send? – Sam Post Jan 31 '10 at 11:57
  • yeah am storing it in a variable called "bytes_sent". And if there are 20 characters sent from the client, the variable correctly shows "20 bytes" sent. Am printing the bytes sent on the command prompt. Also once the connection is closed all the data sent is printed on the server until then there's no data from the client being sent. – MohamedSanaulla Jan 31 '10 at 12:33
  • The data could be stuck in the input buffer on the receiving side; use wireshark to check. Also verify that you set `flag = 1` before calling `setsockopt()` above. – mark4o Feb 01 '10 at 08:16
  • I tried using Wireshark but couldn't figure out any activity which had same IP for source and destination. And also am setting the flag=1. – MohamedSanaulla Feb 01 '10 at 14:03
  • @sana, what is the problem you are trying to solve? – Nikolai Fetissov Feb 01 '10 at 14:12
  • I am implementing the JVMTI Interface in natvie (C++) language (JVMTI Agent). The data obtained from the JVMTI Agent(Client Socket) is being sent to another Java process (Server Socket). Though the data is being printed on the Server socket, its happening only after I exit the Client Socket. – MohamedSanaulla Feb 01 '10 at 15:16

5 Answers5

5

Doing a bit of research on Google, it doesn't seem like there's a way to flush a socket stream explicitly. You can set the TCP_NODELAY and then it will turn off the TCP Nagle algorithm. This should make sure that the data gets sent immediately and not wait until it's buffer is full before sending.

Have you used wireshark or something to see what's going behind the scenes when you set TCP_NODELAY?

Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
  • I haven used any of the tools to check what's happening behind the scenes. Wat i obeserved was that the data gets sent immediately to the server once the socket connection closes or the client completes execution. – MohamedSanaulla Jan 31 '10 at 11:20
  • And even I found that there's no explicit way to flush sockets but there were few telling that they could do it by setting TCP_NODELAY or using shutdown() – MohamedSanaulla Jan 31 '10 at 11:22
  • Without using such tools you can't know that the data was sent when the connection was closed. – nos Jan 31 '10 at 19:36
  • You can disable Nagle, but I don't know a way to disable delayed ACKs, which could also be the problem. – Mooing Duck Mar 13 '14 at 17:46
4

You might want to read The ultimate SO_LINGER page, or: why is my tcp not reliable, which I think applies to your situation.

Edit:

Calling send() on a TCP socket multiple times is not that uncommon :) It's normal usage, I mean. You probably have issues on the server side, where server expects certain number of bytes and blocks waiting for it.
As far as I know JVM TI does not dictate any over-the-wire protocol, so you'll have to come up with your own. Define structure of the record the client sends and server expects, put data length in there if size varies. You might also implement some application-level acknowledgement from server back to client.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
  • I went through the article completely. Though I wasn't able to understand most of it. I could figure out that the Author was trying to tell- use send() and then call shutdown(). But what if i need to send the data multiple times? Its not possible right once shutdown() is called? – MohamedSanaulla Feb 01 '10 at 15:26
  • At the server side am using a Scanner instance to read the stream. So when ever the data is available on the stream the "hasNext()" method returns TRUE and it reads using "next()" method. Do we still need the size of the data sent to be known. – MohamedSanaulla Feb 01 '10 at 16:09
  • 1
    It's better to let the other side know what to expect. The thing is that TCP transfers data in chunks (IP packets), which don't necessarily align with the data the app sends. Ask yourself - how does the server know when one piece of data from the client ends and the other begins? – Nikolai Fetissov Feb 01 '10 at 16:20
  • Actually u were correct. I was making a mistake in the Server side when I was usin Scanner. My friend suggested me to replace it with BufferedReader. I replaced it with BufferedReader to read byte by byte. Thanks a lot for the help. – MohamedSanaulla Feb 01 '10 at 16:34
2

just use fdopen. In Linux anything is a file. eg.

FILE *f = fdopen(socketdescriptor, "w+");
. . .
n = write(socketdescriptor, "this is a message", 17);
fflush(f);

...
ScottJShea
  • 7,041
  • 11
  • 44
  • 67
2

You can't explicitly flush as socket as the data is always sent as soon reasonably possible, taking into account the available buffer space at the receiver and the need to avoid network congestion. Setting TCP_NODELAY permits the sending of packets less than maximum size whilst there are still outstanding acknowledgements.

Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23
  • 2
    That's unfortunate, because what is "reasonable" is debatable. Is it reasonable to have to wait tens of milliseconds when I know I've written all the data to the socket for a command and now I want the server to reply as fast as possible? – Michael Dec 12 '12 at 22:41
1

socket-unix-faq says that you can't flush sockets

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416