2

我在使用 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;
    }

帮助将不胜感激^_^。

4

3 回答 3

3

对不起,但是

 int local;
 (...)
 return (int*)local;

你想达到什么目的?您的代码中有许多严重的问题。

于 2011-09-10T17:41:44.337 回答
2

这不是您通过网络发送数据的方式。错误太多了。

如果您想通过网络发送以空字符结尾的字符串:

int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );

正如大家所说,您实际上并没有发送空终止符。如果您在长度上加 1,您会发送它。此外,对于长字符串,该send()函数不能保证您一次发送整个字符串。您必须检查并重新发送丢失的部分。

recv(ConnectSocket, recvbuf , recvbuflen, 0);

您不检查返回值,因此您无法知道接收到的字符串的长度。由于您不发送空字节,因此接收到的数据不是空终止的。此外,如果空终止符是您发送的更多数据的唯一分隔符,则您必须逐字节读取(效率不高),以免错过空终止符才能知道何时完成。另一种方法是制定自己的缓冲方案(因此下一次读取将部分返回前一次的结果),或更改协议以预先知道传输数据的长度。此外,关于部分读取与send函数的相同评论也适用于此处。

顺便说一句,返回静态/全局缓冲区并不是好代码的标志。

于 2011-09-10T17:53:35.787 回答
1

您并没有真正检查recv.

有一个do-while,但它什么也没做。即使recv失败,您也没有正确处理错误就从函数返回,但您永远不会知道。

此外,您不会发送\0不必要的终止,这取决于您要执行的操作,例如您可以在接收后添加它。

于 2011-09-10T17:16:30.257 回答