如何从客户端接收 int 和 string 的缓冲区,并正确存储它们? (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 "different" 数据类型的缓冲区——字符串和整数。
缓冲区应该是这样的 -
这意味着如果客户端要发送消息代码 200 和数据 "ok",他必须发送缓冲区 [2002ok]。
但我已经决定客户端将缓冲区作为字符发送。
所以,缓冲区看起来像这样- [Èok]
(È = 200的ascii值, = 2的ascii值)
(编辑:我不知道为什么,但是这里不能显示 2 的 ASCII 值..)
问题是,当我解压缩缓冲区的 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);
以下是我使用的 "Helper" 函数(解压数据):
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());
}
}
客户端似乎工作正常 - 它的输出是:
È ok
但是服务器的输出应该是 -
The message code is 200
实际上是
The message code is ├
我的错误在哪里?
谢谢,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;
}
我。 e.您将数据直接写入应放置的位置。同时,您解决了内存泄漏问题...
问题仍然存在于字节顺序......你显然在 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
(thanks, 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)。
我有一个简单的 cpp 服务器,它从 python 客户端接收一个 char * 缓冲区并将其解压缩以使用数据。
python 客户端发送一个包含 2 "different" 数据类型的缓冲区——字符串和整数。
缓冲区应该是这样的 -
这意味着如果客户端要发送消息代码 200 和数据 "ok",他必须发送缓冲区 [2002ok]。 但我已经决定客户端将缓冲区作为字符发送。
所以,缓冲区看起来像这样- [Èok]
(È = 200的ascii值, = 2的ascii值) (编辑:我不知道为什么,但是这里不能显示 2 的 ASCII 值..)
问题是,当我解压缩缓冲区的 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);
以下是我使用的 "Helper" 函数(解压数据):
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());
}
}
客户端似乎工作正常 - 它的输出是:
È ok
但是服务器的输出应该是 -
The message code is 200
实际上是
The message code is ├
我的错误在哪里? 谢谢,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;
}
我。 e.您将数据直接写入应放置的位置。同时,您解决了内存泄漏问题...
问题仍然存在于字节顺序......你显然在 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
(thanks, 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)。