簡體   English   中英

無法通過套接字 C 發送文件

[英]cant send file through socket C

它僅在我使用自己的計算機執行時才有效,但是當我使用另一台計算機時,收到的文件一團糟,並且大小總是另一個。

服務器:

while (1) {
        ZeroMemory(r_buf, MAX_BUFF_RECV - 1);
        bytesReceived = recv(sock, r_buf, FILE_DOWNLOAD_SIZE, 0);

        if (bytesReceived < 0) {
            // ERROR
            puts("[!] recv failed");
            return;
        }
        else if (bytesReceived < FILE_DOWNLOAD_SIZE) {
            // LAST CHUNCK
            if (WriteFile(out, r_buf, bytesReceived, &n, NULL) == FALSE) {
                printf("WriteFile() error %d\n", GetLastError());
            }
            break;
        }
        else {
            if (WriteFile(out, r_buf, bytesReceived, &n, NULL) == FALSE) {
                printf("WriteFile() error %d\n", GetLastError());
            }
        }
    }

客戶:

while (1)
    {
        ZeroMemory(buff, FILE_DOWNLOAD_SIZE);
        nread = fread(buff, 1, FILE_DOWNLOAD_SIZE, f);

        if (nread != FILE_DOWNLOAD_SIZE) {
            send(s, buff, nread, 0);
            break;
        }
        else {
            send(s, buff, nread, 0);
        }
    }

我花了幾個小時,請告訴我出了什么問題

在面向連接的傳輸中,如 TCP, send()recv()不是recv() 無法保證您send()將在單個數據包中傳輸,或者recv()將一次接收您send()所有內容。

無法保證send()甚至會接受您提供的所有內容。 它將盡可能多地復制到套接字的出站緩沖區中,並返回復制的實際字節數。 因此它可以接受比請求更少的字節。

同樣, recv()會將套接字的入站緩沖區中當前可用的任何數據(至少1 個字節但不超過指定的字節數)復制到指定的緩沖區中,並將返回實際復制的字節數。 因此它可以接收比請求更少的字節。

您還需要知道實際傳輸了多少文件數據,以便知道何時停止讀取數據。 由於recv()返回的字節數少於請求的字節數,因此您不能僅依靠緩沖區大小來指示 EOF。

您沒有在代碼中考慮任何這些。

嘗試更像這樣的事情:

服務器:

bool readRaw(SOCKET sock, void *buf, int bufSize)
{
    char *pbuf = (char*) buf;
    while (bufSize > 0)
    {
        int bytesReceived = recv(sock, pbuf, bufSize, 0);
        if (bytesReceived < 0)
        {
            printf("[!] recv() error %d\n", WSAGetLastError());
            return false;
        }
        else if (bytesReceived == 0)
        {
            puts("[!] client disconnected");
            return false;
        }
        else
        {
            pBuf += bytesReceived;
            bufSize -= bytesReceived;
        }
    }
    return true;
}

...

unsigned __int64 fileSize = 0;
if (readRaw(sock, &fileSize, sizeof(fileSize)))
{
    while (fileSize > 0)
    {
        int bufSize = min(fileSize, MAX_BUFF_RECV);

        if (!readRaw(sock, r_buf, bufSize))
            break;

        if (!WriteFile(out, r_buf, bufSize, &n, NULL))
        {
            printf("[!] WriteFile() error %d\n", GetLastError());
            break;
        }

        fileSize -= bufSize;
    }
}

客戶:

bool sendRaw(SOCKET sock, void *buf, int bufSize)
{
    char *pbuf = (char*) buf;
    while (bufSize > 0)
    {
        int bytesSent = send(sock, pbuf, bufSize, 0);
        if (bytesSent < 0)
        {
            printf("[!] send() error %d\n", WSAGetLastError());
            return false;
        }
        else
        {
            pBuf += bytesSent;
            bufSize -= bytesSent;
        }
    }

    return true;
}

...

fseek(f, 0, SEEK_END);
long int pos = ftell(f);
fseek(f, 0, SEEK_SET);

if (pos == -1)
    printf("[!] ftell() error\n");
else
{
    unsigned __int64 fileSize = pos;
    if (sendRaw(s, &fileSize, sizeof(fileSize)))
    {
        while (fileSize > 0)
        {
            int bufSize = min(FILE_DOWNLOAD_SIZE, fileSize);

            nread = fread(buff, 1, bufSize, f);
            if (nread == 0)
            {
                printf("[!] fread() error\n");
                break;
            }

            if (!sendRaw(s, buff, nread))
                break;

            uifileSize -= nread;
        }
    }
}

暫無
暫無

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

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