socket檔案流壓縮傳輸檔案
使用Socket流
設計需求:使用wxWidgets的流,你可以做到使用很少的代碼就可以很容易傳輸很大量的資料。 wxWidgets提供了一種非常簡便的方法。
開發平台:CodeBlock,wxWidgets,win10
因為wxWidgets提供了wxSocketInputStream和wxSocketOutputStream類。通過别的流來将資料讀出或者寫入socket是非常友善的.因為wxWidgets提供了基于檔案,字元串,文本,記憶體以及zlib壓縮的流操作,将這些流和 socket流結合起來使用,可以實作很有趣也是很強大的socket資料操作方法.現在,回過頭來看看我們剛才說的通過socket壓縮傳輸大檔案的問題,我們可能已經找到了一個更友善的途徑.要發送一個檔案,我們可以現将來自檔案的資料流通過zlib的壓縮流以後發送到socket的發送流,這樣我們一下在就有了強大的支援大檔案,支援壓縮的,每次隻需要讀幾K的socket檔案傳輸方法了.而在接收端,我們同樣可以使用流操作将來自socket流的資料通過zlib解壓縮流發送到檔案輸出流,最後還原為原來的檔案.所有這些可能幾行代碼就足夠了.
我們将使用線程來處理整個過程,以便我們可以既不占用100%的CPU,又不阻塞GUI(正如上一小節讨論的那樣),要知道在使用socket傳輸大型的資料的時候,(如果不使用多線程,)這種阻塞幾乎是不可避免的。
實作的基本操作
完整的例子見:https://download.csdn.net/download/qq_23313467/12133442
檔案發送線程(SocketsStreamServer)
下面的例子中示範了流對象在堆上建立,FileSendThread派生自wxThread.
FileSendThread::FileSendThread(wxString Filename,
wxSocketBase* Socket)
{
m_Filename = Filename;
m_Socket = Socket;
Create();
Run();
}
void* FileSendThread::Entry()
{
// 如果10秒之内我們什麼資料都發送不了,就逾時退出
m_Socket->SetTimeout(10);
// 在所有資料發送完成之前,阻塞一切非socket操作
m_Socket->SetFlags(wxSOCKET_WAITALL | wxSOCKET_BLOCK);
// 從特定的檔案流中讀入資料
wxFileInputStream* FileInputStream =
new wxFileInputStream(m_Filename);
// 用來寫入socket的流對象
wxSocketOutputStream* SocketOutputStream =
new wxSocketOutputStream(*m_Socket);
// 我們寫入的将是壓縮以後的資料
wxZlibOutputStream* ZlibOutputStream =
new wxZlibOutputStream(*SocketOutputStream);
// 将檔案的内容寫入壓縮流
ZlibOutputStream->Write(*FileInputStream);
// 寫所有的資料
ZlibOutputStream->Sync();
// 釋放ZlibOutputStream将導緻發送zlib的壓縮結束标記
delete ZlibOutputStream;
// 釋放資源
delete SocketOutputStream;
delete FileInputStream;
return NULL;
}
檔案接收線程(SocketsStreamClient)
接收例子示範了相關流對象也可以在棧上建立.FileReceiveThread派生自wxThread.
FileReceiveThread::FileReceiveThread(wxString Filename,
wxSocketBase* Socket)
{
m_Filename = Filename;
m_Socket = Socket;
Create();
Run();
}
void* FileReceiveThread::Entry()
{
// 如果10秒内什麼也收不到,中止接收
m_Socket->SetTimeout(10);
// 在我們成功接收完資料之前,阻塞一切其它的代碼
m_Socket->SetFlags(wxSOCKET_WAITALL | wxSOCKET_BLOCK);
// 用于輸出資料到檔案的流對象
wxFileOutputStream FileOutputStream(m_Filename);
// 從socket接收資料的流對象
wxSocketInputStream SocketInputStream(*m_Socket);
// zlib解壓縮流對象
wxZlibInputStream ZlibInputStream(SocketInputStream);
// 将解壓縮以後的結果寫入檔案
FileOutputStream.Write(ZlibInputStream);
return NULL;
}
後續問題: 在client端,儲存檔案的時候,有時候會出現錯誤: Error: Can’t read inflate stream: unexpected EOF in underlying stream.
這時候,儲存的檔案有了,但是檔案的大小為0. 是什麼原因導緻這種情況,目前不清楚!