You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Marco Spinetti <m....@pisa.iol.it> on 2004/01/07 14:46:52 UTC

apr_socket_recv

Hi all,

I'm writing to this mail list because I have a problem with apr and I
don't know if it is a bug or an error of mine.

I have installed apr-0.9.4 on my system (RedHat linux 9.0 with
glibc-2.3.2-27.9.7).

I toke client.c inside test directory and I have modified it (only a few
lines) to query a particular system.

The problem is that the function apr_socket_recv doesn't read all the
output but only a part of it. This function returns APR_SUCCESS before
all the output is sent.

Shall I set a particular option?

The program is this.

#include <stdlib.h>
#include "apr_network_io.h"
#include "apr_errno.h"
#include "apr_general.h"
#include <errno.h>

#define STRLEN 40000 
#define GET_CMD   "GET %s HTTP/1.0\r\n\r\n"

int main(int argc, char *argv[])
{
    apr_pool_t *context;
    apr_socket_t *sock;
    apr_size_t length;
    apr_status_t stat;
    char datasend[STRLEN] = "3|0|0|1|<richiesta
tipo=\"domanda\"><t>colombo</t></richiesta>\0";
    char datarecv[STRLEN];
    char msgbuf[80];
    char *local_ipaddr, *remote_ipaddr;
    char *dest = "xxxxxxx";
    apr_port_t local_port, remote_port;
    apr_interval_time_t timeout = apr_time_from_sec(10);
    apr_sockaddr_t *local_sa, *remote_sa;
    int scelta = 0;

    setbuf(stdout, NULL);
    if (argc > 1) {
        dest = argv[1];
    }

    if (argc > 2) {
        scelta = atoi(argv[2]);
    }

    fprintf(stdout, "Initializing.........");
    if (apr_initialize() != APR_SUCCESS) {
        fprintf(stderr, "Something went wrong\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");
    atexit(apr_terminate);

    fprintf(stdout, "Creating context.......");
    if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
        fprintf(stderr, "Something went wrong\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout,"\tClient:  Making socket address...............");
    if ((stat = apr_sockaddr_info_get(&remote_sa, dest, APR_UNSPEC,
(scelta == 0) ? 5500 : 80, 0, context)) 
        != APR_SUCCESS) {
        fprintf(stdout, "Failed!\n");
        fprintf(stdout, "Address resolution failed for %s: %s\n", 
                dest, apr_strerror(stat, msgbuf, sizeof(msgbuf)));
        exit(-1);
    }
    fprintf(stdout,"OK\n");

    fprintf(stdout, "\tClient:  Creating new socket.......");
    if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM,
                          context) != APR_SUCCESS) {
        fprintf(stderr, "Couldn't create socket\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout, "\tClient:  Setting socket timeout.......");
    stat = apr_socket_timeout_set(sock, timeout);
    if (stat) {
        fprintf(stderr, "Problem setting timeout: %d\n", stat);
        exit(-1);
    }

    fprintf(stdout, "\tClient:  Connecting to socket.......");

    stat = apr_socket_connect(sock, remote_sa);

    if (stat != APR_SUCCESS) {
        apr_socket_close(sock);
        fprintf(stderr, "Could not connect: %s (%d)\n", 
		apr_strerror(stat, msgbuf, sizeof(msgbuf)), stat);
        fflush(stderr);
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    apr_socket_addr_get(&remote_sa, APR_REMOTE, sock);
    apr_sockaddr_ip_get(&remote_ipaddr, remote_sa);
    apr_sockaddr_port_get(&remote_port, remote_sa);
    apr_socket_addr_get(&local_sa, APR_LOCAL, sock);
    apr_sockaddr_ip_get(&local_ipaddr, local_sa);
    apr_sockaddr_port_get(&local_port, local_sa);
    fprintf(stdout, "\tClient socket: %s:%u -> %s:%u\n", local_ipaddr,
local_port, remote_ipaddr, remote_port);

    fprintf(stdout, "\tClient:  Trying to send data over
socket.......");
    length = STRLEN;
    if ((stat = apr_socket_send(sock, (scelta == 0) ? datasend :
datasend1, &length) != APR_SUCCESS)) {
        apr_socket_close(sock);
        fprintf(stderr, "Problem sending data: %s (%d)\n",
		apr_strerror(stat, msgbuf, sizeof(msgbuf)), stat);
        exit(-1);
    }
    fprintf(stdout, "OK\n");
   
    length = STRLEN; 
    fprintf(stdout, "\tClient:  Trying to receive data over
socket.......");

    if ((stat = apr_socket_recv(sock, datarecv, &length)) !=
APR_SUCCESS) {
        apr_socket_close(sock);
        fprintf(stderr, "Problem receiving data: %s (%d)\n", 
		apr_strerror(stat, msgbuf, sizeof(msgbuf)), stat);
        exit(-1);
    }
    
    fprintf(stderr, "Out = %s\n", datarecv);

    fprintf(stdout, "\tClient:  Shutting down socket.......");
    if (apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
        apr_socket_close(sock);
        fprintf(stderr, "Could not shutdown socket\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout, "\tClient:  Closing down socket.......");
    if (apr_socket_close(sock) != APR_SUCCESS) {
        fprintf(stderr, "Could not shutdown socket\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    return 1;
}



Can someone help me?

Where is my error?


Thanks for the support


Bye


--Marco



Re: apr_socket_recv

Posted by Jeff Trawick <tr...@attglobal.net>.
Marco Spinetti wrote:
>

> So I have a small question on you reply.
> 
> I can find:
> 
> - EOF controlling if the return state of apr_socket_recv is APR_EOF.
> - an error if  the return state is != APR_SUCCESS

yes

> The reply of my system is dynamic so I suppose that if apr_socket_recv
> replies APR_EOF all my data has been read. 

well, APR_EOF means you've read all you're going to get...  you can't 
know just from seeing APR_EOF whether the peer actually got through 
transferring data or the peer has dropped the connection unexpectedly... 
  if the peer application crashes, you'll eventually get APR_EOF from 
apr_socket_recv()


Re: apr_socket_recv

Posted by Jeff Trawick <tr...@attglobal.net>.
Marco Spinetti wrote:

> but I can't understand how it is useful.

One reason the API is designed that way is because in many cases where 
network apps read from a peer, there is no set number of bytes to expect 
to read; the app simply decides the maximum amount it can handle at a 
time and passes a buffer of that size to the i/o layer.

Also of benefit, even when the app knows it must read a certain number 
of bytes, is the ability to know the progress of the data transfer, 
which returning partial bytes allows.


Re: apr_socket_recv

Posted by Marco Spinetti <m....@pisa.iol.it>.
Ok,

but I can't understand how it is useful.

In real case, you don't know what the reply is and it's length: so you
malloc a buffer big enough and then you read the input.

I suppose that the pointer len tells you the number of bytes read. So
how can you use this information? I think that only the return state of
apr_socket_recv is important.

This is why I have asked these questions.


Regards


--Marco


 

Il mer, 2004-01-07 alle 17:51, Norman Tuttle ha scritto:
> I should also point out that the fact the read will be incomplete is
> implied by the fact that len is a pointer which really means it is both an
> input/output parameter: apr_socket_read will only get (*len) characters.
> 
> -Norman Tuttle ntuttle@photon.poly.edu
> 
> On 7 Jan 2004, Marco Spinetti wrote:
> 
> > Hi Jeff,
> > 
> > thanks very much for your reply.
> > 
> > Sorry but I'm new to apr and when I tried to click on apr-docs link in
> > http://apr.apache.org/ I can't find anything.
> > 
> > So I have a small question on you reply.
> > 
> > I can find:
> > 
> > - EOF controlling if the return state of apr_socket_recv is APR_EOF.
> > - an error if  the return state is != APR_SUCCESS
> > 
> > Is it ok?
> > 
> > The reply of my system is dynamic so I suppose that if apr_socket_recv
> > replies APR_EOF all my data has been read. 
> > 
> > Is it ok?
> > 
> > 
> > Thanks and regards
> > 
> > 
> > --Marco
> > 
> > 
> > 
> > Il mer, 2004-01-07 alle 17:05, Jeff Trawick ha scritto:
> > > Marco Spinetti wrote:
> > > 
> > > > The problem is that the function apr_socket_recv doesn't read all the
> > > > output but only a part of it. This function returns APR_SUCCESS before
> > > > all the output is sent.
> > > > 
> > > > Shall I set a particular option?
> > > 
> > > no, just loop calling apr_recv until you hit an error or EOF or you read 
> > > all you expected
> > > 
> > > we should update the docs to say that it will return partial data... 
> > > since this is the way the raw network APIs work, it probably didn't seem 
> > > interesting to we implementors
> > > 
> > > 
> > 
> > 
> 


Re: apr_socket_recv

Posted by Norman Tuttle <nt...@photon.poly.edu>.
I should also point out that the fact the read will be incomplete is
implied by the fact that len is a pointer which really means it is both an
input/output parameter: apr_socket_read will only get (*len) characters.

-Norman Tuttle ntuttle@photon.poly.edu

On 7 Jan 2004, Marco Spinetti wrote:

> Hi Jeff,
> 
> thanks very much for your reply.
> 
> Sorry but I'm new to apr and when I tried to click on apr-docs link in
> http://apr.apache.org/ I can't find anything.
> 
> So I have a small question on you reply.
> 
> I can find:
> 
> - EOF controlling if the return state of apr_socket_recv is APR_EOF.
> - an error if  the return state is != APR_SUCCESS
> 
> Is it ok?
> 
> The reply of my system is dynamic so I suppose that if apr_socket_recv
> replies APR_EOF all my data has been read. 
> 
> Is it ok?
> 
> 
> Thanks and regards
> 
> 
> --Marco
> 
> 
> 
> Il mer, 2004-01-07 alle 17:05, Jeff Trawick ha scritto:
> > Marco Spinetti wrote:
> > 
> > > The problem is that the function apr_socket_recv doesn't read all the
> > > output but only a part of it. This function returns APR_SUCCESS before
> > > all the output is sent.
> > > 
> > > Shall I set a particular option?
> > 
> > no, just loop calling apr_recv until you hit an error or EOF or you read 
> > all you expected
> > 
> > we should update the docs to say that it will return partial data... 
> > since this is the way the raw network APIs work, it probably didn't seem 
> > interesting to we implementors
> > 
> > 
> 
> 


Re: apr_socket_recv

Posted by Marco Spinetti <m....@pisa.iol.it>.
Hi Jeff,

thanks very much for your reply.

Sorry but I'm new to apr and when I tried to click on apr-docs link in
http://apr.apache.org/ I can't find anything.

So I have a small question on you reply.

I can find:

- EOF controlling if the return state of apr_socket_recv is APR_EOF.
- an error if  the return state is != APR_SUCCESS

Is it ok?

The reply of my system is dynamic so I suppose that if apr_socket_recv
replies APR_EOF all my data has been read. 

Is it ok?


Thanks and regards


--Marco



Il mer, 2004-01-07 alle 17:05, Jeff Trawick ha scritto:
> Marco Spinetti wrote:
> 
> > The problem is that the function apr_socket_recv doesn't read all the
> > output but only a part of it. This function returns APR_SUCCESS before
> > all the output is sent.
> > 
> > Shall I set a particular option?
> 
> no, just loop calling apr_recv until you hit an error or EOF or you read 
> all you expected
> 
> we should update the docs to say that it will return partial data... 
> since this is the way the raw network APIs work, it probably didn't seem 
> interesting to we implementors
> 
> 


Re: apr_socket_recv

Posted by Jeff Trawick <tr...@attglobal.net>.
Marco Spinetti wrote:

> The problem is that the function apr_socket_recv doesn't read all the
> output but only a part of it. This function returns APR_SUCCESS before
> all the output is sent.
> 
> Shall I set a particular option?

no, just loop calling apr_recv until you hit an error or EOF or you read 
all you expected

we should update the docs to say that it will return partial data... 
since this is the way the raw network APIs work, it probably didn't seem 
interesting to we implementors