简体   繁体   English

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

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

I have a simple cpp server which receives a char * buffer from a python client and unpacks it in order to use the data. 我有一个简单的cpp服务器,它从python客户端接收一个char *缓冲区,并将其解包以使用数据。 the python client sends a buffer which includes 2 "different" data types - string and int. python客户端发送一个包含2种“不同”数据类型的缓冲区-字符串和整数。 the buffer should look like this - 缓冲区应如下所示- 缓冲区表示

which means if the client wants to send the message code 200, and the data "ok", he would have to send the buffer [2002ok]. 这意味着如果客户端要发送消息代码200,并且数据“确定”,则他必须发送缓冲区[2002ok]。 But I have decided that the client would send the buffer as chars. 但是我已经决定客户端将缓冲区作为char发送。

so, the buffer would look like this- [Èok] 因此,缓冲区看起来像这样-[Èok]

(È = 200's ascii value, = 2's ascii value) (edit: I don't know why, but the ASCII value of 2 cannot be shown here..) (È= 200的ascii值,= 2的ascii值)(编辑:我不知道为什么,但是这里无法显示ASCII值2。)

The problem is, That when I unpack the 3 parts of the buffer, they are somehow distorted. 问题是,当我打开缓冲区的3个部分的包装时,它们会以某种方式扭曲。

here is my client side (Python): 这是我的客户端(Python):

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

and here is my server side(CPP): 这是我的服务器端(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);

Here are the "Helper" functions I used (unpacking the data): 这是我使用过的“帮助程序”功能(解压缩数据):



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());
    }

}

the client seems to work fine - it's output is: 客户端似乎工作正常-它的输出是:

È ok 好的

but the server's output, which is supposed to be - 但是服务器的输出应该是-

The message code is 200 消息代码是200

is actually 实际上是

The message code is ├ 消息代码为├

Where is my mistake? 我的错误在哪里? Thanks, M. 谢谢,M

You should change the way you receive data: 您应该更改接收数据的方式:

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

instead of internally creating an array. 而不是在内部创建数组。 Then you can do: 然后,您可以执行以下操作:

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;
}

ie you write the data directly to where it shall be placed. 即,您将数据直接写入应放置的位置。 At the same time, you solve your memory leak issue... 同时,您解决了内存泄漏问题...

Problem remains with endianness... You obviously write big endian on python side, but as is shown above, you'll (most likely – it's machine dependent, but big endian machines got very rare these days...) read little endian. 问题仍然是字节序...您显然在python端编写了大字节序,但是如上所示,您(很可能–它是依赖于机器的,但是这些天大字节序的机器变得非常稀少了...)读取小字节序。 To get independent of machine's byte order on C++ side, too, you could modify the code as follows: 为了也独立于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;

Edit: some remarks from the comments, as these have been moved away: 编辑:评论中的一些评论,因为这些评论已被移走:

Well, actually, there's already a function doing this stuff: ntohl (thanks, WhozCraig , for the hint), so you can get it much easier: 好吧,实际上,已经有一个函数正在执行此操作: ntohl (感谢, WhozCraig给出了提示),因此您可以轻松得多:

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

Another problem spotted during discussion, this time on python side: 在讨论中发现的另一个问题,这次是在python方面:

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

encode by default delivers an utf-8 -encoded string, which is certainly not what we want in this case (200 will be converted to two bytes). encode默认情况下,提供了一个utf-8编码过的字符串,这当然不是我们想要在这种情况下,(200将被转换为两个字节)。 Instead we need to use local machine's encoding (on a windows host, quite likely cp1252 for western Europe or cp1250 for central and eastern Europe). 相反,我们需要使用本地计算机的编码(在Windows主机上,西欧很可能是cp1252,中欧和东欧很可能是cp1250)。

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

相关问题 使用python flask从客户端向服务器发送和接收XML文件 - Send and recieve an XML file from client to server using python flask 创建一个Python服务器以从Arduino CC3000客户端接收数据 - Creating a Python server to recieve data from Arduino CC3000 client 将协议缓冲区编码的消息从 Python 服务器发送到 Java 客户端 - Sending Protocol Buffer encoded message from Python Server to Java Client 客户端未收到UDP套接字的消息 - UDP Socket the client does not recieve a message from server Python客户端套接字无法从成功响应中接收数据 - Python client socket can't recieve data from a successful response 如何使Tornado websocket客户端收到服务器通知? - How to make a Tornado websocket client recieve server notifications? Grakn Python 客户端 API - 如何接收事物的某些属性 - Grakn Python client API - How to recieve certain attributes for a thing UDP服务器和客户端无法发送和接收消息 - UDP Server and Client Failing to Send And Recieve Messages 如何使用Python在Server中存储每个客户端(用户)连接? - How to store each Client (User) connection in Server in Python? 如何在 python 中将图片从服务器发送到客户端 - how to send a picture from server to client in python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM