How to send and receive data socket TCP (C/C++) [d

2019-01-20 13:45发布

Possible Duplicate:
What is the correct way of reading from a TCP socket in C/C++?

I'm trying to develop a TCP client/server. My problem is, when I try to send the data from cliente I do it in one sent.

But my problem appears when I try to receive the data with a specific structure, I mean, the first 8 bytes set a date, the next 10 a name, and undefined number of bytes set a text (this text ends with /r/n/r/n)

The client sends as follows:

char date[8];
char name[10];
char msg[4096];

strcpy(msg,"12/10/12"); //8 bytes
strcat(msg,"Kevin Fire"); //10 bytes
strcat(msg,"abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde\r\n\r\n");

nbytes_sent = send(sock,(char *)msg,sizeof(msg),0);
printf("Bytes_sent: %s -> %i\n",msg,nbytes_sent);

And the server try to parse the data from socket as follows:

char date[8];
char name[10];
char * text;
char buf[1024];

int i=0;
for(i=0; i < 8; i++)
    date[i] = '\0';
for(i=0; i < 10; i++)
    name[i] = '\0';

nbytes_read=recv(sclient,(char *)date,sizeof(date),0);
if(nbytes_read > 0){
    printf("Date: %s (%i)\n",date,nbytes_read);
    //cout.flush();
    nbytes_read=recv(sclient,(char *)name,sizeof(name),0);
    if(nbytes_read > 0){
        printf("Name: %s (%i)\n",name,nbytes_read);
        //cout.flush();
        nbytes_read=recv(sclient,(char *)buf,sizeof(buf),0);
        strcpy(text,buf);
        while(nbytes_read > 0){
            nbytes_read=recv(sclient(char*)buf,sizeof(buf),0);
            strcat(text,buf);
        }
    }
}

printf("Date: %s. Name: %s. Text: %s\n",date,name,text);

标签: c sockets tcp
3条回答
手持菜刀,她持情操
2楼-- · 2019-01-20 14:07

Adding to @hmjd's find:

declared at the var decls is your text pointer...

char * text;

then later...

strcpy(text,buf);
while(nbytes_read > 0){
   nbytes_read=recv(sclient(char*)buf,sizeof(buf),0);
   strcat(text,buf);
}

Maybe try setting that 'text' pointer to something beside a random stack value will help as well.

Continuing the barrage, though the following will not necessarily blow up, your date variable as:

char date[8];

on both client and server side The client variable isn't used at all. The server variable, however is:

nbytes_read=recv(sclient,(char *)date,sizeof(date),0);
if(nbytes_read > 0){

Problem is, the date you sent is, in fact, 8 chars wide already: "12/10/12". Therefore, even if you firm-up a null terminator on the end of your string, which you should always do regardless (good practice):

date[ sizeof(date)/sizeof(date[0])-1 ] = 0;

you'll be truncating off the last char of your date.

There are other things wrong with this; we've only pointed out a few. Think about sending length-prefixes with each of these data values in the array, with checks or range to ensure you get what you expected.

Finally, spending some time on the business-end of a debugger would probably do you very well, especially on the server side.

查看更多
一纸荒年 Trace。
3楼-- · 2019-01-20 14:12

Here's a simple "receive all" function:

int recv_all(int sockfd, void *buf, size_t len, int flags)
{
    size_t toread = len;
    char  *bufptr = (char*) buf;

    while (toread > 0)
    {
        ssize_t rsz = recv(sockfd, bufptr, toread, flags);
        if (rsz <= 0)
            return rsz;  /* Error or other end closed cnnection */

        toread -= rsz;  /* Read less next time */
        bufptr += rsz;  /* Next buffer position to read into */
    }

    return len;
}
查看更多
4楼-- · 2019-01-20 14:31

One (repeated) mistake is:

nbytes_read=recv(sclient,(char *)date,sizeof(date),0);

recv() does not null terminate. This means date will not have a null terminator if sizeof(date) bytes is read. This is a problem when a non-null terminated string is passed as an argument to printf() with "%s" format specifier. If the string is non-null terminated you may see garbage characters appearing after the actual string data. You need to read one less than the target buffer and null terminate or use the format specifier "%*.s" that does not require null termination:

printf("%.*s", n, s); /* Prints first 'n' bytes from 's'. */

Note you can initialise a char[] to all nulls instead of using a for:

char date[8] = "";

or you can use memset().

查看更多
登录 后发表回答