SFML 网络 |发送包含超过 sf::Packets 的其他对象的对象会导致空数据
SFML Networking | Sending objects containing other objects over sf::Packets cause null data
我正在尝试将地图数据发送给客户端,它采用包含地图图块坐标的多个向量的形式。整个地图结构可以简化为这样的东西(不是实际代码,但我也使用它重现了问题):
struct Tile {
sf::Vector3<int> coords;
};
struct Map {
Tile tiles[4];
};
然后,我使用这些运算符将此类对象添加到 sf::Packet
:
sf::Packet& operator<<(sf::Packet& packet, sf::Vector3<int> vec) {
return packet << vec.x << vec.y << vec.z;
}
sf::Packet& operator>>(sf::Packet& packet, sf::Vector3<int> vec) {
return packet >> vec.x >> vec.y >> vec.z;
}
sf::Packet& operator<<(sf::Packet& packet, Tile test) {
return packet << test.coords;
}
sf::Packet& operator>>(sf::Packet& packet, Tile test) {
return packet >> test.coords;
}
sf::Packet& operator<<(sf::Packet& packet, Map test) {
for(int i = 0; i < 4; i++) {
packet << test.tiles[i];
}
return packet;
}
sf::Packet& operator>>(sf::Packet& packet, Map test) {
for(int i = 0; i < 4; i++) {
packet >> test.tiles[i];
}
return packet;
}
到这里,应该没有任何问题:必须将地图反序列化为 4 个图块,而这些图块必须反序列化为 sf::Vector3<int>
本身。
然后是发送:
Tile test;
test.coords.x = 42;
test.coords.y = 34;
test.coords.z = 43;
Map test3;
test3.tiles[0] = test;
sf::Packet packet;
packet << test3;
sock.send(packet);
这段代码效果很好(我用GDB检查了packet
的内容,数据确实是一样的)。接收代码在服务器端也能正常工作:
sf::Packet packet;
sock.receive(packet);
Map test;
cout << "packet received" << endl;
检查数据包的内容(仍然使用 GDB)给出了与发送时相同的内容。 test
的内容是随机的(这是正常的,因为还没有初始化)。
真正的问题发生在将实际数据包数据反序列化到 test
变量时:
if(packet >> test) {
cout << test.tiles[0].coords.x;
} else {
cout << "fail" << endl;
}
打印出来的结果是0,反序列化很好(没有"fail"出现在控制台),但是数据不正确。使用 GDB 检查 test
的内容会发现其数组中的每个元素都是 0。这是 GDB 的输出:
(gdb) print test
= {tiles = {{coords = {x = 0, y = 0, z = 0}}, {coords = {x = 0, y = 0, z = 0}}, {coords = {x = 0, y = 0, z = 0}}, {coords = {
x = 0, y = 0, z = 0}}}}
这可能是什么原因造成的?我很确定我在这里做错了什么,但我真的不明白为什么。
在此先感谢您的帮助:)
好的,我终于明白为什么这不起作用了。
答案当然是非常愚蠢的,并且是典型的愚蠢的 C++ 初学者 :D.
在不通过引用传递对象的情况下使用运算符函数没有一次成功的机会(因为变量的内容将保留在运算符函数中并且不会被更改)。
所以,改变这个:
sf::Packet& operator>>(sf::Packet& packet, Map test) {
for(int i = 0; i < 4; i++) {
packet >> test.tiles[i];
}
return packet;
}
对此:
sf::Packet& operator>>(sf::Packet& packet, Map& test) {
for(int i = 0; i < 4; i++) {
packet >> test.tiles[i];
}
return packet;
}
工作得更好:)
我正在尝试将地图数据发送给客户端,它采用包含地图图块坐标的多个向量的形式。整个地图结构可以简化为这样的东西(不是实际代码,但我也使用它重现了问题):
struct Tile {
sf::Vector3<int> coords;
};
struct Map {
Tile tiles[4];
};
然后,我使用这些运算符将此类对象添加到 sf::Packet
:
sf::Packet& operator<<(sf::Packet& packet, sf::Vector3<int> vec) {
return packet << vec.x << vec.y << vec.z;
}
sf::Packet& operator>>(sf::Packet& packet, sf::Vector3<int> vec) {
return packet >> vec.x >> vec.y >> vec.z;
}
sf::Packet& operator<<(sf::Packet& packet, Tile test) {
return packet << test.coords;
}
sf::Packet& operator>>(sf::Packet& packet, Tile test) {
return packet >> test.coords;
}
sf::Packet& operator<<(sf::Packet& packet, Map test) {
for(int i = 0; i < 4; i++) {
packet << test.tiles[i];
}
return packet;
}
sf::Packet& operator>>(sf::Packet& packet, Map test) {
for(int i = 0; i < 4; i++) {
packet >> test.tiles[i];
}
return packet;
}
到这里,应该没有任何问题:必须将地图反序列化为 4 个图块,而这些图块必须反序列化为 sf::Vector3<int>
本身。
然后是发送:
Tile test;
test.coords.x = 42;
test.coords.y = 34;
test.coords.z = 43;
Map test3;
test3.tiles[0] = test;
sf::Packet packet;
packet << test3;
sock.send(packet);
这段代码效果很好(我用GDB检查了packet
的内容,数据确实是一样的)。接收代码在服务器端也能正常工作:
sf::Packet packet;
sock.receive(packet);
Map test;
cout << "packet received" << endl;
检查数据包的内容(仍然使用 GDB)给出了与发送时相同的内容。 test
的内容是随机的(这是正常的,因为还没有初始化)。
真正的问题发生在将实际数据包数据反序列化到 test
变量时:
if(packet >> test) {
cout << test.tiles[0].coords.x;
} else {
cout << "fail" << endl;
}
打印出来的结果是0,反序列化很好(没有"fail"出现在控制台),但是数据不正确。使用 GDB 检查 test
的内容会发现其数组中的每个元素都是 0。这是 GDB 的输出:
(gdb) print test
= {tiles = {{coords = {x = 0, y = 0, z = 0}}, {coords = {x = 0, y = 0, z = 0}}, {coords = {x = 0, y = 0, z = 0}}, {coords = {
x = 0, y = 0, z = 0}}}}
这可能是什么原因造成的?我很确定我在这里做错了什么,但我真的不明白为什么。
在此先感谢您的帮助:)
好的,我终于明白为什么这不起作用了。 答案当然是非常愚蠢的,并且是典型的愚蠢的 C++ 初学者 :D.
在不通过引用传递对象的情况下使用运算符函数没有一次成功的机会(因为变量的内容将保留在运算符函数中并且不会被更改)。
所以,改变这个:
sf::Packet& operator>>(sf::Packet& packet, Map test) {
for(int i = 0; i < 4; i++) {
packet >> test.tiles[i];
}
return packet;
}
对此:
sf::Packet& operator>>(sf::Packet& packet, Map& test) {
for(int i = 0; i < 4; i++) {
packet >> test.tiles[i];
}
return packet;
}
工作得更好:)