我遇到了Winsock2包装器类(客户端服务器)的麻烦,经过无数个小时的困惑,我觉得如果我问你的意见会更好。
更具体地说,问题是每次我使用Send()函数时,客户端和服务器(并非总是!)都会发送一个或两个额外的字节!
例如,我使用SendBytes(“Hello”),Recv函数返回“Hello•”,在字符数组的末尾带有“•”或其他随机字符。
//main.cpp (Client)
#include "Socket.h"
int main()
{
NetworkService::Client cService = NetworkService::Client();
int res = cService.Initialize("127.0.0.1","20248");
if(res == 0){
int local = cService.SendBytes("Hello!");
printf("Bytes Sent: %ld\n", local);
cService.Shutdown();
char* temp = cService.Recv();
printf("String Recieved: %s - Size: %d",temp,strlen(temp));
printf("\nSTRLEN: %d",strlen("X5"));
}
else{
cService.Clean();
}
cService.Close();
while(!kbhit());
return 0;
}
当然,服务器发送字符串“X5”,客户端打印出strlens ......
//The result with "X5" as the dummy text:
String Recieved: X5? - Size: 3 //Notice the extra '?' character
STRLEN: 2
发送//接收功能
int NetworkService::Client::SendBytes(char* lData){
int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );
if (local == SOCKET_ERROR) {
Close();
return WSAGetLastError();
}
return local;
}
char* NetworkService::Client::Recv(){
recv(ConnectSocket, recvbuf , recvbuflen, 0);
return recvbuf;
}
帮助将不胜感激^ _ ^。
答案 0 :(得分:3)
对不起,但是
int local;
(...)
return (int*)local;
你想要达到什么目的?您的代码中存在许多严重问题。
答案 1 :(得分:2)
这不是您通过网络发送数据的方式。错误太多了。
如果您想通过网络发送以空值终止的字符串:
int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );
正如大家所说,你实际上并没有发送空终止符。如果您在长度上添加1,则会发送它。此外,对于长字符串,send()
函数不保证您一次发送整个字符串。您必须检查并重新发送丢失的部分。
recv(ConnectSocket, recvbuf , recvbuflen, 0);
您不检查返回值,因此您无法知道接收字符串的长度。由于您不发送空字节,因此接收的数据不会以空值终止。此外,如果null终止符是您发送的更多数据的唯一分隔符,则必须逐字节读取(不高效),不要错过空终止符以知道何时完成。另一种方法是制定自己的缓冲方案(因此下一次读取将部分返回前一个的结果),或者更改协议以使预先知道的传输数据的长度。此外,与send
函数相同的关于部分读取的注释也适用于此。
BTW返回静态/全局缓冲区并不是好代码的标志。
答案 2 :(得分:1)
您确实检查recv
的返回值。
有一段时间,但它没有做任何事情。即使recv
失败,您也会从函数返回而没有正确的错误处理,但您永远不会知道它。
此外,您不发送不必要的终止\0
,取决于您尝试做的事情,例如您可以在收到后添加。