C++ 正在更改SFML TCP数据包
在SFML论坛上没有得到任何帮助后,我决定看看这里是否有人能提供帮助。我有一个通过TCP连接到服务器应用程序进行自我更新的应用程序。这工作得非常好,除了一个特定的数据包传输,其中数据包以某种方式发生了更改。服务器发送包含数字1的数据包:C++ 正在更改SFML TCP数据包,c++,tcp,packet,sfml,corruption,C++,Tcp,Packet,Sfml,Corruption,在SFML论坛上没有得到任何帮助后,我决定看看这里是否有人能提供帮助。我有一个通过TCP连接到服务器应用程序进行自我更新的应用程序。这工作得非常好,除了一个特定的数据包传输,其中数据包以某种方式发生了更改。服务器发送包含数字1的数据包: pack << sf::Uint8(1); ClientSocket.Send(pack); (其中,pack再次是一个sf::Packet,sock是一个SocketTCP) 然而,不知何故,在我的客户机中,conf的值显示为零(我的调试器确认了
pack << sf::Uint8(1);
ClientSocket.Send(pack);
(其中,pack
再次是一个sf::Packet,sock
是一个SocketTCP)
然而,不知何故,在我的客户机中,conf的值显示为零(我的调试器确认了这一点),并且它的行为也是如此(下一行根据该值进行切换)。我在同一台机器上运行这两个应用程序,它们都将彼此读取为“127.0.0.1”,因此数据包(如果我理解正确的话)不会通过我的路由器,也不会真正离开我的机器。你知道为什么我的数据包被破坏了吗
为了记录在案,如果有任何帮助的话,我正在使用SFML1.6和我的应用程序在Debian挤压Linux机器上运行
编辑:根据请求,这里是我的应用程序中的更多代码
首先,我的客户机中与此更新程序相关的部分:
cout << "Connecting to update server." << endl;
sf::IpAddress server = sf::IpAddress::LocalHost;
sf::TcpSocket sock;
if (sock.connect(server, PORT, sf::seconds(20.0f)) != sf::Socket::Done)
return false;
cout << "Connected. Searching for updates for updater." << endl;
sf::Packet pack;
std::string lastUpdate = getLastUpdate();
#ifdef __WXGTK__
pack << "uupdate" << lastUpdate << sf::Uint8(1);
#elif defined(__WXMSW__)
pack << "uupdate" << lastUpdate << sf::Uint8(2);
#elif defined(__WXOSX__)
pack << "uupdate" << lastUpdate << sf::Uint8(3);
#endif
sock.send(pack);
pack.clear();
sock.receive(pack); //THIS IS THE PART WHERE IT BREAKS
sf::Int32 conf;
pack >> conf;
if (conf == 1) { //There is an update!
cout << "Update found!" << endl;
pack << "begin" << sf::Uint32(512);
sock.send(pack);
pack.clear();
sock.receive(pack);
pack >> conf;
if (conf == 0) { //No errors
wxFileOutputStream* out = new wxFileOutputStream(wxString(UPDATER, StrConv).append(".temp"));
char* data = new char[512];
while (data != chara("done") && data != chara("error")) {
sock.receive(pack);
sf::Int32 size;
pack >> size;
data = const_cast<char*>((const char*)pack.getData());
out->Write(data, size);
}
out->Close();
if (data == chara("done"))
wxCopyFile(wxString(UPDATER, StrConv).append(".temp"), wxString(UPDATER, StrConv));
wxRemoveFile(wxString(UPDATER, StrConv).append(".temp"));
}
}
cout << "Updater is up-to-date. Executing updater." << endl;
sock.disconnect();
bool success;
if (wxTheApp->argc == 1)
success = wxExecute(wxT(UPDATER));
else
success = wxExecute(wxString(UPDATER, StrConv).append(wxTheApp->argv[1]));
return success;
cout这不是一个真正的答案,但我不能对这个问题添加评论,所以
SFML 1.6未维护,如果SFML本身存在问题,则可能已在版本2.0中解决。您可以下载RC。因此,问题相当简单。你知道我是如何在中添加了很多pack.clear()
行的吗?结果我忘记在接收原始数据和在服务器上发送原始数据之间添加一个。因此,我的数据包仍然有第一次调用sock.receive(pack)
时留下的数据(在上面发布的服务器的代码开头上方几行)。我花了这么长时间才看到。调用pack.clear()
,问题就消失了。您确定您正在阅读此数据包而不是上一个数据包的剩余内容吗?是的。我使用的是阻塞套接字,我保证服务器上的每个发送调用都与客户端上的一个接收调用相匹配(反之亦然)。我还看到,我的客户机确实挂起了上面显示的Receive调用,直到服务器发出上面显示的Send调用。更不用说之前的数据包在任何地方都没有0。请尝试更改数据类型/值以查看它是全部还是只是uint8。可能我正在以某种方式读取前一个数据包中的值。我将其更改为Uint16
并继续得到0,但随后我将其更改为Int32
,现在得到的是7。我不明白为什么。客户端做的最后一件事是发送数据包,而不是接收数据包,sf::SocketTCP::send(sf::packet)
应该清空数据包中的所有数据,我相信……在翻遍SFML源代码之后,情况似乎不是这样:send(sf::packet)
没有清除数据包。因此,我似乎仍在读取数据包中的旧数据,而不是刚刚发送的数据。我将尝试添加一些对sf::Packet::Clear()
的调用,看看这是否能解决问题。明天学徒队列询问时,我将能够发布更多代码,但现在我想发表我已更新到2.0的评论,我仍然看到同样的问题。正如我所说,我明天会发布更多的代码。@学徒,我已经添加了源代码,希望它能解决这个问题。
cout << "Connecting to update server." << endl;
sf::IpAddress server = sf::IpAddress::LocalHost;
sf::TcpSocket sock;
if (sock.connect(server, PORT, sf::seconds(20.0f)) != sf::Socket::Done)
return false;
cout << "Connected. Searching for updates for updater." << endl;
sf::Packet pack;
std::string lastUpdate = getLastUpdate();
#ifdef __WXGTK__
pack << "uupdate" << lastUpdate << sf::Uint8(1);
#elif defined(__WXMSW__)
pack << "uupdate" << lastUpdate << sf::Uint8(2);
#elif defined(__WXOSX__)
pack << "uupdate" << lastUpdate << sf::Uint8(3);
#endif
sock.send(pack);
pack.clear();
sock.receive(pack); //THIS IS THE PART WHERE IT BREAKS
sf::Int32 conf;
pack >> conf;
if (conf == 1) { //There is an update!
cout << "Update found!" << endl;
pack << "begin" << sf::Uint32(512);
sock.send(pack);
pack.clear();
sock.receive(pack);
pack >> conf;
if (conf == 0) { //No errors
wxFileOutputStream* out = new wxFileOutputStream(wxString(UPDATER, StrConv).append(".temp"));
char* data = new char[512];
while (data != chara("done") && data != chara("error")) {
sock.receive(pack);
sf::Int32 size;
pack >> size;
data = const_cast<char*>((const char*)pack.getData());
out->Write(data, size);
}
out->Close();
if (data == chara("done"))
wxCopyFile(wxString(UPDATER, StrConv).append(".temp"), wxString(UPDATER, StrConv));
wxRemoveFile(wxString(UPDATER, StrConv).append(".temp"));
}
}
cout << "Updater is up-to-date. Executing updater." << endl;
sock.disconnect();
bool success;
if (wxTheApp->argc == 1)
success = wxExecute(wxT(UPDATER));
else
success = wxExecute(wxString(UPDATER, StrConv).append(wxTheApp->argv[1]));
return success;
//ClientSocket has already been initalised by way of a TcpListener
cout << "Checking for updater patches for client at " << ClientAddress.toString() << endl;
std::string lastUpdate;
pack >> lastUpdate;
sf::Uint8 os;
pack >> os;
//Check last time updater was changed
struct tm* clock;
struct stat attribs;
if (os == 1)
stat("Linux/Updater", &attribs);
else if (os == 2)
stat("Windows/Updater.exe", &attribs);
else if (os == 3)
stat("Mac/Updater", &attribs);
clock = gmtime(&(attribs.st_mtime));
time_t lastWrite = mktime(clock);
time_t clientUpdate = stringToNumber<time_t>(lastUpdate.c_str());
if (lastWrite > clientUpdate) {
cout << "Found updater patches for client at " << ClientAddress.toString() << endl;
pack << sf::Int32(1);
ClientSocket->send(pack); //THIS IS THE PART WHERE IT BREAKS
pack.clear();
ClientSocket->receive(pack);
std::string mes;
pack >> mes;
if (mes != "begin") {
cerr << "Client at " << ClientAddress.toString() << " sent unrecognised message: " << mes << ". Ending conversation." << endl;
ClientSocket->disconnect();
return false;
}
sf::Uint32 size;
pack >> size;
cout << "Beginning to send updater patch to " << ClientAddress.toString() << endl;
ifstream in;
if (os == 1)
in.open(chara("Linux/Updater"), ios_base::in | ios_base::binary);
else if (os == 2)
in.open(chara("Windows/Updater.exe"), ios_base::in | ios_base::binary);
else if (os == 3)
in.open(chara("Mac/Updater"), ios_base::in | ios_base::binary);
if (in.fail()) {
pack << sf::Uint8(1);
ClientSocket->send(pack);
cerr << "Failed to open updater at request of " << ClientAddress.toString() << ". Closing connection." << endl;
ClientSocket->disconnect();
return false;
}
pack << sf::Uint8(0);
ClientSocket->send(pack);
pack.clear();
//Get length of file
in.seekg(0, ios::end);
int length = in.tellg();
in.seekg(0, ios::end);
char* buf = new char[size];
for (unsigned int i = 0; i < length / size; i++) { //Read and send every `size`-sized block we can
in.read(buf, size);
pack << sf::Int32(size) << buf;
ClientSocket->send(pack);
}
in.read(buf, length % size);
pack << sf::Int32(length % size) << buf;
ClientSocket->send(pack);
pack.clear();
pack << "done";
ClientSocket->send(pack);
pack.clear();
} else {
pack << sf::Int8(0);
ClientSocket->send(pack);
}