天天看點

socket檔案流壓縮傳輸檔案

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. 是什麼原因導緻這種情況,目前不清楚!