持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
- 英文小册原文地址: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);
}
当部分数据包到达时,接收器端会发生什么?
如果数据包是可变长度的,接收方如何知道一个数据包何时结束,另一个何时开始?
现实世界的情景百出往往最让我们头疼。你必须得使用封装(忘记这个概念的话点我)来解决这个问题喽。
下文见!