如何发送和接收数据套接字TCP(C / C ++)

可能重复:
在C / C ++中从TCP套接字读取的正确方法是什么?

我正在尝试开发TCP客户端/服务器。 我的问题是,当我尝试从客户端发送数据时,我会在一次发送中执行此操作。

但是当我尝试接收具有特定结构的数据时出现我的问题,我的意思是,前8个字节设置日期,接下来的10个名称和未定义的字节数设置文本(此文本以/ r / n结尾) / R / N)

客户端发送如下:

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); 

并且服务器尝试从socket解析数据,如下所示:

 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  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); 

这是一个简单的“全部接收”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; } 

一个(重复的)错误是:

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

recv()不会终止null。 这意味着如果读取sizeof(date)字节,则date不会有空终止符。 当非空终止字符串作为参数传递给带有"%s"格式说明符的printf()时,这是一个问题。 如果字符串非空终止,您可能会在实际字符串数据后面看到乱码字符。 您需要读取少于目标缓冲区的一个并且null终止或使用不需要空终止的格式说明符"%*.s"

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

请注意,您可以将char[]初始化为所有空值,而不是使用for

 char date[8] = ""; 

或者您可以使用memset()

添加到@hmjd的查找:

在var decls声明的是你的文本指针……

 char * text; 

然后……

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

也许尝试将“text”指针设置为随机堆栈值旁边的某些内容也会有所帮助。

继续弹幕,虽然以下不一定会爆炸,你的date变量为:

 char date[8]; 

客户端和服务器端都没有使用客户端变量。 但是服务器变量是:

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

问题是,你发送的日期实际上已经是8个字符宽:“12/10/12”。 因此,即使你在字符串末尾固定一个空终结符,你应该总是这样做(不错的做法):

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

你将截断你约会的最后一个字符。

这还有其他问题; 我们只指出了一些。 考虑使用数组中的每个数据值发送长度前缀,并使用检查或范围来确保获得预期的结果。

最后,花一些时间在调试器的业务端可能会对你做得很好,特别是在服务器端。