0

SFML フォーラムで何の助けも得られなかったので、ここにいる誰かが助けてくれるかどうかを確認することにしました。サーバー アプリケーションへの TCP 接続を介して自身を更新するアプリケーションがあります。これは、パケットが何らかの形で変更される特定のパケット送信を除いて、完全に正常に機能します。サーバーは、番号 1 を含むパケットを送信します。

pack << sf::Uint8(1);
ClientSocket.Send(pack);

(packは sf::PacketClientSocket型で、 sf::SocketTCP 型です)

実際、デバッガーを使用してステップ実行すると、これらの行が実行され、クライアントでの次の Receive 呼び出しが次の数行であることが確認されます。

sock.Receive(pack);
sf::Uint8 conf;
pack >> conf;

(ここpackでも sf::Packet でありsock、SocketTCP です)

しかし、どういうわけか私のクライアントでは、conf の値がゼロとして表示され (私のデバッガーはこれを確認します)、そのように動作します (値に応じて次の行が切り替わります)。同じマシンで両方のアプリケーションを実行していますが、どちらも「127.0.0.1」としてお互いを読み取っているため、パケットは (正しく理解していれば) ルーターを通過していないか、実際にマシンから出ていません。パケットが破損している理由について何か考えはありますか?

参考までに、私は SFML 1.6 を使用しており、アプリケーションは Debian Squeeze 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;

次に、これらの更新に関連するサーバーの部分:

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

編集: ここに投稿されてからほぼ 1 か月が経ちましたが、まだ問題があります。私はこれを解決する方法について頭を悩ませています。

4

2 に答える 2

1

これは実際には答えではありませんが、質問にコメントを追加できないので...

SFML 1.6 は維持されておらず、SFML 自体に問題がある場合は、バージョン 2.0 で既に解決されている可能性があります。RCはここからダウンロードできます。

于 2012-09-04T09:03:02.197 に答える
0

したがって、問題はかなり単純であることがわかりました。pack.clear()私がたくさんの行を追加した方法を知っていますか?元のデータを受信して​​からサーバーに元のデータを送信するまでの間に1つ追加するのを忘れたことがわかりました。そのため、私のパケットには、への最初の呼び出しからまだデータが残っていましたsock.receive(pack)(これは、上記のサーバーからのコードの開始より数行上でした)。それを見るのにこれほど長い時間がかかりました。に電話をかけるpack.clear()と、問題は解決しました。

于 2013-01-17T01:16:44.897 に答える