可能重复:
What is the correct way of reading from a TCP socket in C/C++?
我正在尝试开发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 < 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);
答案 0 :(得分:6)
这是一个简单的“全部接收”功能:
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;
}
答案 1 :(得分:1)
一个(重复的)错误是:
nbytes_read=recv(sclient,(char *)date,sizeof(date),0);
recv()
不会终止。这意味着如果读取date
个字节,sizeof(date)
将没有空终止符。当非空终止字符串作为参数传递给具有printf()
格式说明符的"%s"
时,这是一个问题。如果字符串非空终止,您可能会在实际字符串数据后面看到乱码字符。您需要读取少于目标缓冲区的一个并且null终止或使用不需要空终止的格式说明符"%*.s"
:
printf("%.*s", n, s); /* Prints first 'n' bytes from 's'. */
请注意,您可以将char[]
初始化为所有空值,而不是使用for
:
char date[8] = "";
或者您可以使用memset()
。
答案 2 :(得分:1)
添加到@ hmjd的find:
在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;
你将截断你约会的最后一个字符。
这还有其他问题;我们只指出了一些。考虑使用数组中的每个数据值发送长度前缀,并使用检查或范围来确保获得预期的结果。
最后,花一些时间在调试器的业务端可能会对你做得很好,特别是在服务器端。