tags:

views:

430

answers:

3

EDIT: the code below has been fixed to receive and send properly AND to account for the actual bytes of messages sent annd recieved (latter thanks to EJP)

Hey guys, I'm programming in C, Unix.

I have server and client that are supposed to exchange msgs. While client seems to send messages fine, server doesn't receive the messages the client is sending. I've tried using recv() and read() (i know they are practically the same thing but with extra flags on recv()) but I have no luck and I'm not really sure what the problem really is.

i put sleep(3) in the client code after every time it sends a message but i see that once client and server are connected, server immediately closes without waiting for the incoming messages. what am i doing wrong?? Thanks for any inputs.

this is the client side code

#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE   500

int main(int argc, char * argv[])
{
    int sockfd;
    char * host;
    char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/
    int msg_len;

    struct hostent * hp;
    struct sockaddr_in client_address, server_address;


    printf("y halo thar\n");


    // looking up from the host database
    if (argc == 2)
        host = argv[1];
    else
        exit(1);
    printf("sdf\n");


    hp = gethostbyname(host);
    if (!hp)
        exit(1);
    printf("host found\n");


    // setting up address and port structure information
    bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
    server_address.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
    server_address.sin_port = htons(SERVER_TCP_PORT);
    printf("set\n");


    // opening up socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        exit(1);
    printf("opened\n");


    // connecting
    if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
        exit(1);
    printf("connected\n");


    int i;

    for (i = 0; i < MAX_DATA_SIZE; ++i)
    {
        msg[i] = '.';
    }

    msg[MAX_DATA_SIZE-1] = '\0';

    for(i = 0; i < 11; i++)
    {
        // send message to connected socket
        msg_len = write(sockfd, msg, MAX_DATA_SIZE);
        if(msg_len < 1)
            printf("notsent\n");
        else
            printf("%i  bytes sent\n", msg_len);

        // recieve messages from connected socket
        msg_len = read(sockfd, msg, MAX_DATA_SIZE);
        if (msg_len < 1)
            printf("not recieved\n");
        else
        {
            printf("%i bytes received\n", msg_len);
            printf(msg);
            printf("\n");

        }
    }


    // close connection
    close(sockfd);
    printf("closed\n");

}

and this is the server side

#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE   500


int main()
{

    printf("o halo thar\n");

    int sockfd, new_sockfd;
    int client_addr_len;
    char msg [MAX_DATA_SIZE];
    int msg_len;
    char got_msg [11] = "got ur msg\0";
    struct sockaddr_in server_address, client_address;


    // setting up address and port structure information
    bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(SERVER_TCP_PORT);


    // opening up socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        exit(1);
    printf("socket is opened\n");


    // binding
    if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
        exit(1);
    printf("socket is bound\n");


    // listening
    listen(sockfd,5);
    printf("listening\n");

    // block and wait for an incoming connection

    client_addr_len = sizeof(client_address);
    new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
    if (new_sockfd < 0)
        exit(1);

    printf("accepted\n");


    int i;

    for( i = 0; i < 11; i++)
    {
        // recieve messages from connected socket
        printf("waiting\n");
        msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
        if (msg_len < 1)
        {
            printf("no msg recieved\n");    
        }
        else
        {
            printf("bytes recieved: %i\n", msg_len);
        }


        // send message to connected socket
        msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
        if (msg_len < 1)
            printf("not sent\n");
        else
            printf("%i bytes sent\n", msg_len);
    }


    // close connection
    close(sockfd);
    printf("socket closed. BYE! \n");


}
A: 

is the implementation based on stream or datagram?

there are some problem with your operation flow. the server might start to read before client send anything.

since client and server are separated, you can imagine them running concurrently. right after your server side "accept" connection request, there might be possibly some handshake overhead occurs or network delays causing server app to execute ahead in time, attempt to extract data but meet with errors (no data received yet). you can try this out by adding sleep in server code after accept connection, where client should have enough time to send the data.

another better solution is to make data retrieval cope with empty buffer or asynchronous read.

YeenFei
There is no problem at all with the server calling `read` before the client sends anything. The `read` call will simply block until data is available. "No data recieved yet" is **not** an error.
caf
And there's no need for a sleep either.
EJP
I only added sleep() in client side to locate what the problem was but I really can't (and shouldn't have to) use sleep() since the purpose of this program is to measure packet round trips.
Fantastic Fourier
+3  A: 

In the server code, the problem is on this line:

msg_len = read(sockfd, msg, MAX_DATA_SIZE);

You are calling read on sockfd, but you need to call read or recv on new_sockfd (the socket returned by accept()). new_sockfd is the one that's connected to the client (sockfd is used to accept further connections - eg if another client connects).

caf
Thanks that solved the problem!!! And yea, that makes a lot more sense to read from the new socket file descriptor from accept().
Fantastic Fourier
You are also ignoring the counts returned by read() and write() apart from checking them for errors. You can't do that: you must use them to determine how much data was actually read or written. You can't assume your request was fulfilled completely.
EJP
EJP the code now does account for actual bytes of msgs sent and received. Thanks.
Fantastic Fourier
A: 

You should read from the socket returned by accept.

Try to call read on the socket returned from accept.

stefanB
The message sent by the client clearly starts with a `'.'` character.
caf
oh, i was looking at wrong part of code
stefanB