还记得前面的 send() 章节吗?当时我不是提过 send() 可能不会将你所要求的数据全部送出吗?也就是说,虽然你想要送出 512 bytes,但是 send() 只送出 412 bytes。那剩下的 100 个 bytes 到哪去了呢? 好的,其实它们还在你的缓冲区里。因为环境不是你能控制的,kernel 会决定要不要用一个 chunk 将全部的数据送出,而现在,我的朋友,你可以决定要如何处理缓冲区中剩下的数据。 你可以写一个像这样的函数: #include <sys/types.h> #include <sys/socket.h> int sendall(int s, char *buf, int *len) { int total = 0; // 我们已经送出多少 bytes 的数据 int bytesleft = *len; // 我们还有多少数据要送 int n; while(total < *len) { n = send(s, buf+total, bytesleft, 0); if (n == -1) { break; } total += n; bytesleft -= n; } *len = total; // 返回实际上送出的数据量 return n==-1?-1:0; // 失败时返回 -1丶成功时返回 0 }在这个例子里,s 是你想要传送数据的 socket,buf 是储存数据的缓冲区,而 len 是一个指针,指向一个 int 型别的变数,记录了缓冲区中的数据数量。 函数在错误时返回 -1[而 errno 仍然从调用 send() 设置]。还有,实际送出的数据数量会在 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); }当数据包的一部分抵达接收端(receiver end)时会发生什麽事情呢?如果数据包的长度是会变动的(variable),接收端要如何知道另一端的数据包何时开始与结束呢? 是的,你或许必须封装(encapsulate)[还记得数据封装(data encapsulation)章节的开头那边吗?那边有详细说明]。 |
07-高等技术 >