2012-09-03 35 views
0

在SFML論壇未能獲得任何幫助後,我決定查看是否有人可以獲得幫助。我有一個應用程序,它通過TCP連接更新到服務器應用程序。除了一個特定的數據包傳輸,其中數據包以某種方式被改變之外,這工作得很好。服務器發送一個包含數字1包:我的調試器步進通過正在更改的SFML TCP數據包

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

(其中pack的類型是科幻::包和ClientSocket的類型是科幻:: SocketTCP)

事實上確實確認這些線路被執行,並且在我的客戶端下一個接收呼叫接下來的幾行:

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

(其中pack再次是SF ::包,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); 
} 

編輯:我知道這是近一個月以來,在這裏有任何帖子,但我仍然有這個問題。我很機智的結束如何解決這個問題。

+0

你確定你正在閱讀這個包,而不是最後一個的剩菜? – Dani

+0

是的。我正在使用阻塞套接字,並且我確保服務器上的每個發送呼叫都與客戶端上的一個接收呼叫匹配(反之亦然)。我也看到我的客戶端掛在上面顯示的接收呼叫上,直到服務器發送上面顯示的發送呼叫。 更不用說,在那之前的數據包在任何地方都沒有0。 –

+0

嘗試更改數據類型/值以查看它是一切還是隻是uint8。 – Dani

回答

0

所以,原來問題很簡單。你知道我是如何添加大量pack.clear()行的嗎?事實證明,我忘了在接收原始數據和在服務器上發送原始數據之間添加一個。所以我的數據包仍然有數據從第一次調用到sock.receive(pack)(這是從上面發佈的服務器的代碼開始的幾行)剩餘的數據。我花了很長時間纔看到這一點。打電話給pack.clear(),問題就消失了。

1

這是不是一個真正的答案,但我不能添加的問題,所以評論...

SFML 1.6不能維持,如果有與SFML本身的問題,它可能已經在版本來解決2.0。您可以下載RC here

+0

明天我可以發佈更多的代碼作爲Apprentice Queue,但現在我想發表評論,我已更新到2.0,而且我仍然看到同樣的問題。正如我所說,明天我會發布更多的代碼。 –

+0

@Apprentice,我已經添加了源代碼,希望它可以解決問題。 –