Home > Archive > Unix Programming > August 2006 > multiple recv() calls required
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
multiple recv() calls required
|
|
| Simon Morgan 2006-08-21, 7:01 pm |
| Can somebody please explain why it takes (at least) 2 calls to recv() to
fetch a definition from a DICT server, regardless of whether the DEFINE
command is sent before or after the first recv()?
The way I see it is:
* I connect() and the server sends the banner, but I don't recv() it. * I
send the DEFINE command.
* The server sends the definition.
* I call recv().
What I don't understand is why recv() only copies the server banner into
the buffer when there is enough room for part of the definition as well.
The man page mentions "messages" which hints at an explanation but is
somewhat at odds with my idea of TCP as being about sending and receiving
streams of data.
Here's some example code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
int main(int argc, char *argv[]) {
char *cmd = "DEFINE english hello\n";
char buffer[256];
int sockfd, n;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
server = gethostbyname("dict.org");
bzero(&serv_addr, sizeof serv_addr);
serv_addr.sin_family = AF_INET;
bcopy(server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(2628);
connect(sockfd, (struct sockaddr *)&serv_addr, sizeof serv_addr) < 0;
n = send(sockfd, cmd, strlen(cmd), 0);
/* first call only gets banner */
bzero(buffer, sizeof buffer);
n = recv(sockfd, buffer, 255, 0);
printf("%d\n%s", n, buffer);
/* this time we get (part of) the definition */
bzero(buffer, sizeof buffer);
n = recv(sockfd, buffer, 255, 0);
printf("%d\n%s", n, buffer);
return 0;
}
| |
| David Schwartz 2006-08-21, 7:01 pm |
|
Simon Morgan wrote:
> Can somebody please explain why it takes (at least) 2 calls to recv() to
> fetch a definition from a DICT server, regardless of whether the DEFINE
> command is sent before or after the first recv()?
>
> The way I see it is:
>
> * I connect() and the server sends the banner, but I don't recv() it. * I
> send the DEFINE command.
> * The server sends the definition.
> * I call recv().
>
> What I don't understand is why recv() only copies the server banner into
> the buffer when there is enough room for part of the definition as well.
> The man page mentions "messages" which hints at an explanation but is
> somewhat at odds with my idea of TCP as being about sending and receiving
> streams of data.
Why do you care? You have to keep calling 'recv()' until you get all
the data the protocol says you should get anyway.
DS
| |
| Alex Fraser 2006-08-21, 7:01 pm |
| "Simon Morgan" <nobody@example.net> wrote in message
news:44e9d4ee$0$2550$fa0fcedb@news.zen.co.uk...
> Can somebody please explain why it takes (at least) 2 calls to recv() to
> fetch a definition from a DICT server, regardless of whether the DEFINE
> command is sent before or after the first recv()?
>
> The way I see it is:
>
> * I connect() and the server sends the banner, but I don't recv() it.
> * I send the DEFINE command.
> * The server sends the definition.
> * I call recv().
Firstly, I would be surprised if this is allowed by the protocol. That is, I
expect the protocol says you must wait for the banner before sending a
command. Failure to do this could potentially cause deadlock, but in
practice, in this particular case, you are likely to get away with it.
Secondly, the steps above probably don't happen in the order you describe.
In particular, the last step most likely happens before the server receives
the DEFINE command, so it can't possibly have sent the definition.
The behaviour you are seeing is probably a consequence of the precise timing
of events. Try using tcpdump or similar to capture the packets sent and
received and you may be able to find (or make a good guess at) the reason.
> What I don't understand is why recv() only copies the server banner into
> the buffer when there is enough room for part of the definition as well.
> The man page mentions "messages" which hints at an explanation but is
> somewhat at odds with my idea of TCP as being about sending and receiving
> streams of data.
If you mean that the recv() man page mentions messages, recv() can be used
on datagram sockets, which do work with messages.
Alex
| |
| Simon Morgan 2006-08-21, 7:01 pm |
| On Mon, 21 Aug 2006 17:25:47 +0100, Alex Fraser wrote:
> Firstly, I would be surprised if this is allowed by the protocol. That
> is, I expect the protocol says you must wait for the banner before
> sending a command. Failure to do this could potentially cause deadlock,
> but in practice, in this particular case, you are likely to get away
> with it.
>
> Secondly, the steps above probably don't happen in the order you
> describe. In particular, the last step most likely happens before the
> server receives the DEFINE command, so it can't possibly have sent the
> definition.
>
> The behaviour you are seeing is probably a consequence of the precise
> timing of events. Try using tcpdump or similar to capture the packets
> sent and received and you may be able to find (or make a good guess at)
> the reason.
Looks like you were spot on. I placed a sleep() call right after the
send() and now the definition appears in the buffer after the first
recv(). I also ran tcpdump with both bits of code and in the non-sleep()
case a RST packet seems to be sent immediately after a large packet is
received which I assume is the definition. With the sleep() call added the
RST isn't sent until after an ACK for the large packet.
I should mention that my primary aim isn't to write a standards compliant
dict client but rather to learn about sockets. This was simply a "hello,
world" type thing.
Thanks for your help.
| |
| Nils O. SelÄsdal 2006-08-21, 7:01 pm |
| Simon Morgan wrote:
> On Mon, 21 Aug 2006 17:25:47 +0100, Alex Fraser wrote:
>
>
> Looks like you were spot on. I placed a sleep() call right after the
> send() and now the definition appears in the buffer after the first
> recv(). I also ran tcpdump with both bits of code and in the non-sleep()
> case a RST packet seems to be sent immediately after a large packet is
> received which I assume is the definition. With the sleep() call added the
> RST isn't sent until after an ACK for the large packet.
>
> I should mention that my primary aim isn't to write a standards compliant
> dict client but rather to learn about sockets. This was simply a "hello,
> world" type thing.
If learning sockets, and TCP is the goal, you must be aware that TCP
provides a stream interface to users. There is no concept of
"messages/boundaries".
One send call might result in several recv calls on the other side,
or many send calls might result in one recv call on the other side -
you can't know.
| |
| Rick Jones 2006-08-21, 7:01 pm |
| Simon Morgan <nobody@example.net> wrote:
> Looks like you were spot on. I placed a sleep() call right after the
> send() and now the definition appears in the buffer after the first
> recv(). I also ran tcpdump with both bits of code and in the
> non-sleep() case a RST packet seems to be sent immediately after a
> large packet is received which I assume is the definition. With the
> sleep() call added the RST isn't sent until after an ACK for the
> large packet.
There shouldn't be any RST's. If the connection is to be closed there
should be FINished segments, not ReSeT's. Either there is a botch in
the application close handshaking, or the remote is doing something
patently stupid like using an abortive close().
rick jones
--
oxymoron n, Hummer H2 with California Save Our Coasts and Oceans plates
these opinions are mine, all mine; HP might not want them anyway... :)
feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...
|
|
|
|
|