繁体   English   中英

如何从客户端接收整数和字符串的缓冲区并正确存储它们? (cpp服务器,python客户端)

[英]How to recieve a buffer of ints and strings from a client , and store them right? (cpp server , python client)

我有一个简单的cpp服务器,它从python客户端接收一个char *缓冲区,并将其解包以使用数据。 python客户端发送一个包含2种“不同”数据类型的缓冲区-字符串和整数。 缓冲区应如下所示- 缓冲区表示

这意味着如果客户端要发送消息代码200,并且数据“确定”,则他必须发送缓冲区[2002ok]。 但是我已经决定客户端将缓冲区作为char发送。

因此,缓冲区看起来像这样-[Èok]

(È= 200的ascii值,= 2的ascii值)(编辑:我不知道为什么,但是这里无法显示ASCII值2。)

问题是,当我打开缓冲区的3个部分的包装时,它们会以某种方式扭曲。

这是我的客户端(Python):

msg = chr(200) + chr(0) + chr(0) + chr(0) + chr(2) + "ok"
print(">>>>" + (msg)) 
sock.send((msg.encode()))

这是我的服务器端(CPP):

           uint8_t  msgCode = helpMe.getCode(client_socket);
           std::cout << "The message code is " << static_cast<unsigned int>(msgCode) << std::endl;
           int DataLen = helpMe.getLength(client_socket);
           std::string StrData = helpMe.getString(client_socket, DataLen);

这是我使用过的“帮助程序”功能(解压缩数据):



using std::string;

uint8_t Helper::getCode(SOCKET sc)
{
    uint8_t code;
    getPartFromSocket(sc, reinterpret_cast<char*>(&code), sizeof(code), 0);
    return code;
}

uint32_t Helper::getLength(SOCKET sc)
{
        uint32_t length;
        getPartFromSocket(sc, reinterpret_cast<char*>(&length), sizeof(length), 0);
        return length;
}

std::string Helper::getString(SOCKET sc, size_t length)
{
    std::string s(length + 1, 0);
    getPartFromSocket(sc, (char*)s.data(), length, 0);
    // possible since C++17   ^
    return s;
}

void Helper::getPartFromSocket(SOCKET sc, char * buffer, size_t bytesNum, int flags)
{
    if (bytesNum == 0)
    {
        return;
    }

    int res = recv(sc, buffer, bytesNum, flags);

    if (res == INVALID_SOCKET)
    {
        std::string s = "Error while recieving from socket: ";
        s += std::to_string(sc);
        throw std::exception(s.c_str());
    }

}

客户端似乎工作正常-它的输出是:

好的

但是服务器的输出应该是-

消息代码是200

实际上是

消息代码为├

我的错误在哪里? 谢谢,M

您应该更改接收数据的方式:

void Helper::getPartFromSocket(SOCKET sc, char* buffer, size_t bytesNum, int flags);

而不是在内部创建数组。 然后,您可以执行以下操作:

uint8_t Helper::getCode(SOCKET sc)
{
    uint8_t code;
    getPartFromSocket(sc, reinterpret_cast<char*>(&code), sizeof(code), 0);
    return code;
}
uint32_t Helper::getLength(SOCKET sc)
{
    uint32_t length;
    getPartFromSocket(sc, reinterpret_cast<char*>(&length), sizeof(length), 0);
    return length;
}
std::string Helper::getString(SOCKET sc, size_t length)
{
    std::string s(length, 0);
    getPartFromSocket(sc, s.data(), length, 0);
    // possible since C++17   ^
    return s;
}

即,您将数据直接写入应放置的位置。 同时,您解决了内存泄漏问题...

问题仍然是字节序...您显然在python端编写了大字节序,但是如上所示,您(很可能–它是依赖于机器的,但是这些天大字节序的机器变得非常稀少了...)读取小字节序。 为了也独立于C ++端的机器字节顺序,您可以按以下方式修改代码:

uint32_t length = 0
for(unsigned int i = 0; i < sizeof(length); ++i)
{
    uint8_t byte;
    getPartFromSocket(sc, reinterpret_cast<char*>(&byte), sizeof(byte), 0);
    // little endian tranmitted:
    // length |= static_cast<uint32_t>(byte) << 8*i;
    // big endian transmitted:
    length |= static_cast<uint32_t>(byte) << 8*(sizeof(length) - (i + 1));
    // simpler: just adjust loop variable; = 1, <= sizeof            ^
}
return length;

编辑:评论中的一些评论,因为这些评论已被移走:

好吧,实际上,已经有一个函数正在执行此操作: ntohl (感谢, WhozCraig给出了提示),因此您可以轻松得多:

uint32_t length;
getPartFromSocket(sc, reinterpret_cast<char*>(&length), sizeof(length), 0);
return ntohl(length);

在讨论中发现的另一个问题,这次是在python方面:

sock.send((msg.encode()))

encode默认情况下,提供了一个utf-8编码过的字符串,这当然不是我们想要在这种情况下,(200将被转换为两个字节)。 相反,我们需要使用本地计算机的编码(在Windows主机上,西欧很可能是cp1252,中欧和东欧很可能是cp1250)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM