在客户端和服务器程序之间发送和接收消息给我意想不到的结果
Sending and receiving messages between client and server program giving me unexpected result
这是我的服务器程序代码:
...
listen(s , 3);
//Accept and incoming connection
cout<<"\n\nWaiting for incoming connections... ";
int c = sizeof(sockaddr_in);
Socket newSocket = accept(s , (struct sockaddr *)&client, &c);
if (newSocket == INVALID_SOCKET)
{
cout<<"\nAccept failed with error code : "<<WSAGetLastError();
}
// Since both server and client are now connected, it's time to send and receive players' name
string me;
char other[30];
fi.close(); fi.open("data.dat");
fi>>me; fi.close();
recv(newSocket,other,strlen(other),0);
send(newSocket,me.c_str(),me.length(),0);
cout<<me<<endl<<other;
这是客户端程序代码:
Socket s;
//Connect to server
if (connect(s , (sockaddr *)&server , sizeof(server)) < 0)
{
cout<<"\nConnection error.";
_getch();
return 1;
}
//reading name and sending it to server
string me;
char other[30];
ifstream fi("cdata.dat");
fi>>me; fi.close();
send(s,me.c_str(),me.length(),0);
recv(s,other,strlen(other),0);
cout<<me<<endl<<other;
假设 data.dat
包含单词 Hero
cdata.dat
包含单词 'Zero'
现在服务器端输出是(忽略其他行):
Hero
Zero%$#5^sdj
客户端输出为(忽略其他行):
Zero
He
有什么问题?
您的 'other' 数组长度为 30,但是您没有通过 recv 的 return 值(即已读取的字节数)裁剪该数组的长度.
另外,另一个数组的 strlen 是危险的,因为它不是以 null 结尾的字符串,而是一个恒定大小的数组,您应该使用该数组的长度而不是 strlen。
我相信如果您在客户端中做同样的事情,它也会解决这个问题。另一个数组在未初始化时可能包含一个随机空字节,这将给出一个您不期望的奇数 strlen 值。
您在这里错误地使用了函数strlen
。这通过搜索字符 [=14=]
(空终止符)的第一次出现来确定 c
字符串的长度。鉴于您没有初始化 other
数组,此值将是随机的,而不是您可能期望的 30。
您可以更改代码以明确指定数字 30 作为要接收的最大字节数。您还可以通过将发送的字符串长度加 1 来显式发送空终止符。所以服务器代码变成:
recv(newSocket,other,30,0);
send(newSocket,me.c_str(),me.length()+1,0);
客户端代码变为:
send(s,me.c_str(),me.length()+1,0);
recv(s,other,30,0);
最好还是在 other
声明和上面的 recv
用法中将硬编码的 30
更改为某个整数常量。
这是我的服务器程序代码:
...
listen(s , 3);
//Accept and incoming connection
cout<<"\n\nWaiting for incoming connections... ";
int c = sizeof(sockaddr_in);
Socket newSocket = accept(s , (struct sockaddr *)&client, &c);
if (newSocket == INVALID_SOCKET)
{
cout<<"\nAccept failed with error code : "<<WSAGetLastError();
}
// Since both server and client are now connected, it's time to send and receive players' name
string me;
char other[30];
fi.close(); fi.open("data.dat");
fi>>me; fi.close();
recv(newSocket,other,strlen(other),0);
send(newSocket,me.c_str(),me.length(),0);
cout<<me<<endl<<other;
这是客户端程序代码:
Socket s;
//Connect to server
if (connect(s , (sockaddr *)&server , sizeof(server)) < 0)
{
cout<<"\nConnection error.";
_getch();
return 1;
}
//reading name and sending it to server
string me;
char other[30];
ifstream fi("cdata.dat");
fi>>me; fi.close();
send(s,me.c_str(),me.length(),0);
recv(s,other,strlen(other),0);
cout<<me<<endl<<other;
假设 data.dat
包含单词 Hero
cdata.dat
包含单词 'Zero'
现在服务器端输出是(忽略其他行):
Hero
Zero%$#5^sdj
客户端输出为(忽略其他行):
Zero
He
有什么问题?
您的 'other' 数组长度为 30,但是您没有通过 recv 的 return 值(即已读取的字节数)裁剪该数组的长度.
另外,另一个数组的 strlen 是危险的,因为它不是以 null 结尾的字符串,而是一个恒定大小的数组,您应该使用该数组的长度而不是 strlen。
我相信如果您在客户端中做同样的事情,它也会解决这个问题。另一个数组在未初始化时可能包含一个随机空字节,这将给出一个您不期望的奇数 strlen 值。
您在这里错误地使用了函数strlen
。这通过搜索字符 [=14=]
(空终止符)的第一次出现来确定 c
字符串的长度。鉴于您没有初始化 other
数组,此值将是随机的,而不是您可能期望的 30。
您可以更改代码以明确指定数字 30 作为要接收的最大字节数。您还可以通过将发送的字符串长度加 1 来显式发送空终止符。所以服务器代码变成:
recv(newSocket,other,30,0);
send(newSocket,me.c_str(),me.length()+1,0);
客户端代码变为:
send(s,me.c_str(),me.length()+1,0);
recv(s,other,30,0);
最好还是在 other
声明和上面的 recv
用法中将硬编码的 30
更改为某个整数常量。