2

I am attempting to set up a server/client model. The client will receive two matrices from the user, then send these two matrices to the server, which will then compute their product and send the result back to the client, which shall print the result. I encode the matrices as a C-string and send them to the server, where it should be decoded. My code looks as follows:

The client sends the two matrices using the following code:

send_all( sockfd, send_str, strlen(send_str) );
shutdown( sockfd, SHUT_WR ); // Close the write side of socket, since sending is done.

Where send_all is:

void send_all( int socket, char *data, size_t len )
{
    size_t i;
    for( i = 0; i < len; i += send( socket, data, len - i, 0 );
    {
        printf("%d bytes sent to server.\n", len - i); // To confirm send to user
    }
}

My server then receives the the data as follows:

while( len = recv( connfd, buffer, MAX_LINE, 0 ) > 0 )
{
    printf("%d bytes read.\n", len); // To confirm receive to user.
    buffer[len] = '\0';
    strcat(input, buffer);
}
if( len < 0 )
{
    printf("Read error.");
}

The server then parses the string and computes the product, then sending the data in the same manner as the client, where the client receives the data in the same manner as the server.

When I run this program, the client prints that it has sent the correct number of bytes, for example:

406 bytes sent to server.

The server then prints (consistently, no matter the size of the string I send):

72720 bytes read.

and when attempting to print the string, it appears to be garbage.

I am running the client and server in separate Cygwin terminals, using the local host 127.0.0.1, and it appears that they connect successfully.

What am I doing wrong? Am I sending/receive the data in the correct manner? Will my method result in input being identical to send_str? Thank you for your help.

EDIT: I have seen many questions on here and else where addressing difficulties with send() and recv() but I have found no explanation of why recv would be returning such a large number when only a much smaller number of bytes are sent.

Johndt
  • 4,187
  • 1
  • 23
  • 29
  • 1
    you aren't supplying a value to the `printf` function to the server. It is just junk data that is printing out. – NickC Mar 26 '14 at 21:31
  • 1
    `printf("%d bytes read.\n");` seems to miss the integer variable to be printed. – alk Mar 26 '14 at 21:31
  • Oops, I have it in my code, just forgot to add it here. It should print len, the number of bytes recieved, or the return value of recv. Fixing now – Johndt Mar 26 '14 at 21:32
  • 1
    How are `buffer` and `input` and `len` declared? What is `MAX_LINE`? – alk Mar 26 '14 at 21:33
  • @alk Both as char *, with space declared using malloc. So char *buffer = (char *) malloc( sizeof(char) * MAX_LINE ) );, where MAX_LINE is 2048, I believe. EDIT: And len as an int. – Johndt Mar 26 '14 at 21:35
  • 1
    Presumably you are setting `input[0]=0` before reading, for `strcat` to work. – 001 Mar 26 '14 at 21:38
  • No, however, would input = ""; work? – Johndt Mar 26 '14 at 21:42
  • 1
    @JohnT No, you don't want to do that. You will be changing the pointer. User `input[0]=0`. – 001 Mar 26 '14 at 21:52
  • 1
    IS this qustion about C or C++? – alk Mar 26 '14 at 21:54
  • @Johnny Mopp Changed it, and no difference. But thank you for the fix. – Johndt Mar 26 '14 at 21:58
  • C. I can remove the C++ tag, I suppose. Sorry. – Johndt Mar 26 '14 at 21:59
  • If it's C then you could also remove all this castings from your code, that I assume are there. There are few situaton where you need to cast in C. – alk Mar 26 '14 at 21:59

2 Answers2

4

EDIT: I have seen many questions on here and else where addressing difficulties with send() and recv() but I have found no explanation of why recv would be returning such a large number when only a much smaller number of bytes are sent.

I think len is incorrect because operator "=" has less priority then operator ">". You can try to use brackets.

You can see that len has different values in following example:

#include <stdio.h>                                                                                  

int f()                                                                                             
{                                                                                                   
    return 40;                                                                                      
}                                                                                                   
int main()                                                                                          
{                                                                                                   
    int len;                                                                                        
    if(len = f() > 0)                                                                               
    {                                                                                               
        printf("len = %d\n", len);                                                                  
    }                                                                                               


    if((len = f()) > 0)                                                                             
    {                                                                                               
        printf("len = %d\n", len);                                                                  
    }                                                                                               
    return 0;                                                                                       
}         
Sandro
  • 2,707
  • 2
  • 20
  • 30
1

For starters: To print size_t use "zu".

If the modifier "z" is not available check for the size of size_t and either use "lu" (64bit) or "u" (32bit).

In any case "d" is wrong as it's for signed integers and size_t is unsigned.


Also the code fully misses to check the system calls send() and recv() for errors. Both return ((ssize_t) -1) on error, a signed value.


Also^2 the code ignores the fact, that recv() might return few as it was told to receive.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Ah, I have len declared as an int. Should I declare it as type ssize_t, as it says recv returns, here: http://linux.die.net/man/2/recv . Can I not cast the return value as an int? – Johndt Mar 26 '14 at 21:39
  • Casting the return value of recv as an int changes nothing. The same number is still printed out. Also, my actual code does the error checking, and neither return errors. I guess I should have added it. – Johndt Mar 26 '14 at 21:47
  • 1
    If a function requieres a specific type, simply use it. – alk Mar 26 '14 at 21:50
  • 2
    The `send_all()` as you show it does not check for errors. Even more it'll get totally confused in case `-1` would be returned by `send()`. – alk Mar 26 '14 at 21:51
  • I borrowed it from http://stackoverflow.com/questions/13479760/c-socket-recv-and-send-all-data where. In any case, it does not seem to be returning an error, as it prints the correct number of bytes sent. – Johndt Mar 26 '14 at 21:54
  • 1
    It does not necessarily depend on the code using a function whether it might fail or not. Especially if external resources as the network are involved. Do always check read/write functions' outcome! – alk Mar 26 '14 at 21:58
  • 1
    @JohnT It doesn't work at all. See my new comment there. – user207421 Mar 26 '14 at 21:59
  • @EJP I changed the for statement to: for( i = 0;( (i < len) || (i < 1) ); i += send( socket, *data+i, len - i, 0 ) ) Would this work correctly? It also seems that the program sent the entire string in one send call anyways, so it wasn't necessarily affecting the outcome. But thank you for pointing that out, as it is very important! Looking at the other recent comments now, thanks everyone. EDIT: Oops, meant just data+i not *data+i (I think?) – Johndt Mar 26 '14 at 22:06
  • 1
    That won't work either. You're still not terminating correctly on error. You need to *store* the result of `send()` *directly* into a variable, test it for negative, and break if so, otherwise add it to `i`. You can't do this elegantly with a `for` loop, `+=`, etc. – user207421 Mar 26 '14 at 22:40