天天看點

socket不完整傳輸的後續處理

  • 英文小冊原文位址:beej.us/guide/bgnet…
  • 作者:Beej
  • 中文翻譯位址:www.chanmufeng.com/posts/netwo…

回想一下之前我講過的send()​函數,我當時說過,​

​send()​

​​可能不會一下子把你所有的資料都發送出去,比如你想放一個長度為​

​512​

​​位元組的字元串,​

​send()​

​​的傳回值卻是​

​412​

​​。你可能不禁會問到,剩下的​

​100​

​位元組怎麼辦?

其實這​

​100​

​位元組仍然在你小得可憐的緩沖區(buffer)中,等着你把他們發送出去呢!畢竟事事無法如你所願,核心也會有自己的小脾氣,有時就是不想把你的資料一下子發送出去,你還得自己動手把剩下的資料發送出去。

你可以這麼寫:

#include <sys/types.h>
#include <sys/socket.h>

int sendall(int s, char *buf, int *len)
{
    int total = 0;        // how many bytes we've sent
    int bytesleft = *len; // how many we have left to send
    int n;

    while(total < *len) {
        n = send(s, buf+total, bytesleft, 0);
        if (n == -1) { break; }
        total += n;
        bytesleft -= n;
    }

    *len = total; // return number actually sent here

    return n==-1?-1:0; // return -1 on failure, 0 on success      

上例中,​

​s​

​​是你想發送資料的​

​socket​

​​,​

​buf​

​​是儲存資料的緩沖區(buffer),​

​len​

​​指向一個​

​int​

​類型的變量,這個變量記錄了緩沖區剩餘資料的大小。

​send()​

​​異常時會傳回​

​-1​

​​,并且最終實際發送的位元組數量儲存在了​

​len​

​​變量中。​

​sendall()​

​​會竭盡全力發送你所有的資料,除非發生了錯誤會導緻立即傳回,否則​

​len​

​的值一定就是你想發送的資料的長度。

為了完整性,給一個使用​

​sendall()​

​函數的例子:

char buf[10] = "Beej!";
int len;

len = strlen(buf);
if (sendall(s, buf, &len) == -1) {
    perror("sendall");
    printf("We only sent %d bytes because of the error!\n", len);
}      

當部分資料包到達時,接收器端會發生什麼?