I need to enforce the return value of read from a socket to equal to zero without closing connection.
I read the following statement in a page saying:
If an end-of-file condition is received or the connection is closed, 0 is returned.
But I don't know how to make it receive that condition after the string I have sent.
Can anyone help?
I'm afraid you can't do that.
If you want read to return zero, you need to close the socket. If you don't want to close the socket, you need to signal "end-of-communication" or "end-of-message" as part of your protocol.
A common way of doing that is prefixing each message with its length. That way the receiving side knows when it's read a complete message and do whatever it wants with it.
If you want the peer's read() or recv() to return zero, you must either close the socket or shut it down for output. In either case you can't sent anything else afterwards. If that constraint doesn't suit you, you will have to revise your requirement, as it doesn't make sense.
Both the "end of file condition" and the "connection closed" condition tell the receiver that no more data can be received on this socket. You cannot simulate that by sending some magic data.
Besides of calling close on the socket you can use shutdown(2) on the socket to only close either the reading side or the writing side. This might help in limited cases but not in the general case.
Perhaps you need some multiplexing syscall like poll(2).
You definitely need to read some good material like Advanced Linux Programming or Advanced Unix Programming.
If you need the TCP/IP transmission to transit application messages, you need to care about packaging and fragmenting explicitly yourself (either by having fixed-size messages, or by having some way to know the logical message size during transmission). Be aware that TCP/IP transmission can be fragmented by the network.
Related
I'm writing a cross-platform client application that uses sockets, written in C++. I'm having problems where the server is doing a hard close on the socket when it's done sending me info.
I've been reading other posts on this topic, and I'm not so much interested in the rights or wrong of this approach, but it's seems the server is either explicitly setting SO_LINGER=0, or that's the default behavior on that system (not sure, it's a Linux box).
I can see (in Wireshark) that the data was sent to me followed within milli-seconds by an RST, indicating a hard close by the server. I personally don't agree with this approach as it should be up to the client to shutdown the socket.
Server team are saying there's nothing wrong with that approach (doing a hard close rather than shutdown), it's typical on servers to avoid accumulating TIMED_WAIT sockets. On Windows my select() returns indicating there's something to read (while I haven't read any of this "in transit" data yet).
However, because of the quick arrival of the RST, on Windows recv() returns -1 and I'm seeing a 10054 for the error code (connection reset by peer). This wouldn't be too bad if I could at least get the data that was sent, but it seems that once my client's socket stack sees the RST any unread bytes are no longer made available to me.
On Linux (client), there's no problem. It seems the TCP stack is behaving slightly differently, in that I can read the outstanding bytes before the RST is honoured. I'm having trouble convincing the server guys they have a bug, given that it works for a Linux client.
First off, am I correct? Is this a server-side issue? I can't see that the client end is doing anything wrong, so it must be right?
It seems the server team are adamant that they want to perform the close, and they don't want to in have TIMED_WAITs, so I was going to push for them to add a SO_LINGER of, say 2 seconds? Does that sound like it will solve my problem? From what I understand this will stop the server from sending out a RST so soon after sending data, and should give me a chance to read the outstanding bytes.
Found a definitive answer to my own question:
"...Upon reception of RST segment, the receiving side will immediately abort the connection. This statement has more implications than just meaning that you will not be able to receive or send any more data to/from this connection. It also implies that any unread data still in the TCP reception buffer will be lost..." It cites the book "TCP/IP Internetworking Volume II". I don't have that book, so I can only take his word for it. Doesn't seems to discard data on Linux, only Windows...
Olivier Langlois's blog
The side-effect of fiddling with SO_LINGER to force a reset is that all pending data is lost. The fact that you don't receive it is all the proof you need that the server team is wrong to do this.
RFC 793 cited below says 'this command [ABORT] causes all pending SENDs and RECEIVEs to be aborted, ... and a special RESET message to be sent to the TCP on the other side of the connection.' See also W.R. Stevens, TCP/IP Illustrated, Vol. 1, p. 287: 'Aborting a connection provides two features to the application: (1) any queued data is thrown away and the reset is sent immediately, and (2) the receiver of the RST can tell that the other end did an abort instead of a normal close'. There is similar wording, along with an extract from the BSD code that implements it, in Vol. 2.
The TIME_WAIT state only occurs on a socket which sends a FIN before it has received one: see RFC 793. So the server should be waiting for a FIN from the client, with a suitable timeout, rather than resetting. This will also permit the client to do connection pooling.
I read somewhere that every TCP connection has it's own 125kB output and input buffer. What happens if this buffer is full, and I still continue sending data on linux?
According to http://www.kernel.org/doc/man-pages/online/pages/man2/send.2.html the packets are just silently dropped, without notifying me. What can I do to stop this from happening? Is there any way to find out if at least some of my data has been sent correctly, so that I can continue at a later point in time?
Short answer is this. "send" calls on a TCP socket will just block until the TCP sliding window (or internal queue buffers) opens up as a result of the remote endpoint receiving and consuming data. It's not much different than trying to write bytes to a file faster than the disk can save it.
If your socket is configured for non-blocking mode, send will return EWOULDBLOCK or EAGAIN, until data can be sent. Standard poll, select, and epoll calls will work as expected so you know when to "send" again.
I don't know that the "packets are dropped". I think that what is more likely is that the calls that the program makes to write() will either block or return a failure.
I want to know whether its possible for tcp socket to report any broken pipe error immediately. Currently i am catching the sigpipe signal at the client side when server goes down ... but i found that the sigpipe signal is generated
only after 2nd msg is sent from client to server . what could be the possible reason for this?? If the other socket end went down , then the 1st send must return sigpipe .. y isnt that signal generated immediately..??
Is there any possible explanation to this peculiar behaviour?? And any possible way to get around this??
The TCP stack will only throw an error after some number of retransmission attempts. IIRC, the TCP retransmission timer is initialized to some small number of seconds and the number of retransmissions is typically 5-10. The protocol does not support any other means of detecting a peer that has become unreachable during a data exchange, (ie. someone tripped over the server power cable).
I think using SO_KEEPALIVE option may speed up broken link detection.
I want to know whether its possible for tcp socket to report any broken pipe error immediately
The other end of the pipe is across a network. That network could be slow and unreliable. So one end of the pipe can never instantly tell whether its partner still there. The delay could be quite long, so the O/S is also likely to do some bufferring. These considerations make it practically impossible to immediately detect a broken pipe.
And any possible way to get around this
But why would you want to? The pipe could be broken at any time during trans mission, so you have to handle the general case anyway.
I have a problem - when I'm trying to send huge amounts of data through posix sockets ( doesn't matter if it's files or some data ) at some point I don't receive what I expect - I used wireshark to determine what's causing errors, and I found out, that exactly at the point my app breaks there are packets marked red saying "zero window" or "window full" sent in both directions.
The result is, that the application layer does not get a piece of data sent by send() function. It gets the next part though...
Am I doing something wrong?
EDIT:
Lets say I want to send 19232 pieces of data 1024 bytes each - at some random point ( or not at all ) instead of the 9344th packet I get the 9345th. And I didn't implement any retransmission protocol because I thought TCP does it for me.
Zero Window / Window Full is an indication that one end of the TCP connection cannot recieve any more data, until its client application reads some of the data is has already recieved. In other words, it is one side of the connection telling the other side "do not send any more data until I tell you otherwise".
TCP does handle retransmissions. Your problem is likely that:
The application on the recieving side is not reading data fast enough.
This causes the recieving TCP to report Window Full to the sending TCP.
This in turn causes send() on the sending TCP side to return either 0 (no bytes written), or -1 with errno set to EWOULDBLOCK.
Your sending application is NOT detecting this case, and is assuming that send() sent all the data you asked to send.
This causes the data to get lost. You need to fix the sending side so that it handles send() failing, including returning a value smaller than the number of bytes you asked it to send. If the socket is non-blocking, this means waiting until select() tells you that the socket is writeable before trying again.
First of all, TCP is a byte stream protocol, not a packet-based protocol. Just because you sent a 1024 byte chunk doesn't mean it will be received that way. If you're filling the pipe fast enough to get a zero window condition (i.e., that there is no more room in either a receive buffer or send buffer) then it's very likely that the receiver code will at some point be able to read far more at one time than the size of your "packet".
If you haven't specifically requested non-blocking sockets, then both send and recv will block with a zero window/window full condition rather than return an error.
If you want to paste in the receiver-side code we can take a look, but from what you've described it sounds very likely that your 9344th read is actually getting more bytes than your packet size. Do you check the value returned from recv?
Does in your network iperf also fails to send this number of packets of this size? If not check how they send this amount of data.
Hm, from what I read on Wikipedia this may be some kind of buffer overflow (receiver reports zero receive window). Just a guess though.
I am facing an issue with recv() and send() winsock api. Recv() hangs while receving the last packet.
Problem Description:-
System A's app is writing data over a non-blocking socket and system B's app is receiving data over a blocking socket in chunks of 64k.
It seems that while reading probably the last packet of 64k, which may less than or equal to 64k, the receive freezes. I am not sure if the receive of the last packet or send of the last packet is an issue, but I am observing this issue intermittently in our legacy applications.
Has anyone faced a similar issue before? If yes, then can please provide your inputs.
If not, then can you please provide some trouble-shooting techniques to narrow down to the root cause.
Just for information I have win2k3 servers.
Thanks,
Varun
Wireshark is a great tool for troubleshooting networking code. It'll show you exactly what packets are entering and leaving your network interface in near real time.
As to your specific issue: are you saying that the last chunk of data might be shorter than 64k? If so, your protocol should include some message length information so the receiver
knows how much data to look for.
A couple of guesses...
If you are using UDP, perhaps one or more packets are being dropped en route (which UDP is permitted to do whenever it feels like). In that case, your receiver might end up waiting for data that is simply never going to arrive; to fix this you would need to either implement some way of automatically resending the lost data, or (if you don't strictly need all the data), some way for the sender to notify the receiver that he is done transmitting, so the receiver might as well stop waiting. (of course you would need to handle the case where this notification gets dropped, as well... it can get complicated if you want 100% robustness)
If you are using TCP, perhaps you are not carefully checking the values returned by send() on the sending side? If you are assuming that send() will always send the number of bytes you asked it to, you might end up thinking send() sent all the bytes when in fact it only sent some (or none) of them... so the sender would think the transmission was complete, while the receiver would be stuck waiting for data that isn't going to arrive.
You might have a problem with the server sending data down the wire faster than the receiver is able to read it. You could try increasing the receive buffer:
int nSocketBuffer = 131072; // 128k
if (setsockopt(m_sSocket,SOL_SOCKET,SO_RCVBUF,(LPCSTR)&nSocketBuffer,sizeof(int)) == SOCKET_ERROR)
{
// socket error
return false;
}