簡體   English   中英

如何通過Linux套接字發送圖像數據

[英]How to send image data over linux socket

我有一個用C ++編寫的相對簡單的Web服務器。 它可以很好地服務於text / html頁面,但是編寫方式似乎無法發送二進制數據,我確實需要能夠發送圖像。

我一直在搜索,但找不到針對這個問題的答案,這個問題是用真實的C ++編寫的(fstream而不是使用文件指針等),盡管這種事情一定是低級的,並且可能需要處理字節在C樣式數組中,我希望代碼盡可能地為C ++。

我嘗試了幾種方法,這是我目前擁有的方法:

int sendFile(const Server* serv, const ssocks::Response& response, int fd)
{
// some other stuff to do with headers etc. ........ then:

    // open file
    std::ifstream fileHandle;
    fileHandle.open(serv->mBase + WWW_D + resource.c_str(), std::ios::binary);

    if(!fileHandle.is_open())
    {            
        // error handling code
        return -1;
    }

    // send file
    ssize_t buffer_size = 2048;
    char buffer[buffer_size];

    while(!fileHandle.eof())
    {
        fileHandle.read(buffer, buffer_size);

        status = serv->mSock.doSend(buffer, fd);
        if (status == -1)
        {
            std::cerr << "Error: socket error, sending file\n";
            return -1;
        }
    }
    return 0
}

然后在其他地方:

int TcpSocket::doSend(const char* message, int fd) const
{
    if (fd == 0)
    {
         fd = mFiledes;
    }

    ssize_t bytesSent = send(fd, message, strlen(message), 0);
    if (bytesSent < 1)
    {
        return -1;
    }

    return 0;
}

正如我所說,問題在於,當客戶端請求圖像時,它將無法正常工作。 我進入std :: cerr“錯誤:套接字錯誤正在發送文件”

編輯:我使用我接受的答案中的建議使其工作。 為了完整性和幫助那些找到這篇文章的人,我還要發布最終的工作代碼。

為了發送,我決定使用std :: vector而不是char數組。 主要是因為我認為這是一種更C ++的方法,並且很清楚地表明數據不是字符串。 這可能不是必需的,而是一個品味的問題。 然后,我對為該流讀取的字節進行計數,並將其傳遞給send函數,如下所示:

// send file
std::vector<char> buffer(SEND_BUFFER);
while(!fileHandle.eof())
{
    fileHandle.read(&buffer[0], SEND_BUFFER);
    status = serv->mSock.doSend(&buffer[0], fd, fileHandle.gcount());
    if (status == -1)
    {
        std::cerr << "Error: socket error, sending file\n";
        return -1;
    }
}

然后將實際的發送功能進行如下修改:

int TcpSocket::doSend(const char* message, int fd, size_t size) const
{
    if (fd == 0)
    {
        fd = mFiledes;
    }

    ssize_t bytesSent = send(fd, message, size, 0);
    if (bytesSent < 1)
    {
        return -1;
    }

    return 0;
}

您應該更改的第一件事是while (!fileHandle.eof())循環,因為它不會按您期望的那樣工作,實際上,它將迭代一次,因為直到嘗試之后才設置eof標志從文件末尾讀取。 相反,例如while (fileHandle.read(...))

您應該做的第二件事是檢查實際上從文件中讀取了多少字節,並僅發送該字節數。

最后,您讀取的是二進制數據,而不是文本,因此您不能對從文件讀取的數據使用strlen


關於二進制文件問題的一些解釋:您應該希望知道,C樣式的字符串(使用strlen來獲取長度的字符串)以零字符'\\0' (簡而言之,為零字節)終止。 隨機二進制數據在其中任何位置都可以包含很多零字節,這是一個有效字節,沒有任何特殊含義。

當您使用strlen獲取二進制數據的長度時,存在兩個可能的問題:

  1. 數據中間有一個零字節。 這將導致strlen提前終止並返回錯誤的長度。

  2. 數據中沒有零字節。 這將導致strlen超出緩沖區的末尾以尋找零字節,從而導致undefined behavior

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM