C ++,Send()函数发送额外的字节

时间:2011-09-10 17:09:49

标签: c++ sockets networking winsock winsock2

我遇到了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;
    }

帮助将不胜感激^ _ ^。

3 个答案:

答案 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,取决于您尝试做的事情,例如您可以在收到后添加。