免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7496 | 回复: 7

socket: write(fd,buf,size) 什么时候返回值小于size [复制链接]

论坛徽章:
0
发表于 2012-02-21 13:24 |显示全部楼层
int sd, bytes_written = 0, retval;
sd = socket(AF_INET, SOCK_STREAM, 0);
... /*** Connect to host ***/
while ( bytes_written < len ) /* repeat sending until all */
{ /*...bytes of message are sent */
retval = write(sd, buffer+bytes_written, len);
if ( retval >= 0 )
bytes_written += retval;
else
/*---report connection error---*/
}

FILE *sp;
int sd;
sd = socket(AF_INET, SOCK_STREAM, 0);
... /*** Connect to host ***/ sp = fdopen(sd, "w"); /* create FILE* from socket */
if ( sp == NULL )
perror("FILE* conversion failed");
fprintf(sp, "%s, %s, %s\ n",Name, Address, Phone);


Note that in the first example, the program has to loop on the write() to get all the bytes out. Even though this is a socket stream, you cannot guarantee that the program sends all the bytes at once. The second instance does not have that limitation, because FILE* has its own data-buffering subsystem. When you write to a FILE* buffer, the subsystem forces you to wait until it sends all the bytes.

黑体部分不太懂, 还望指教

论坛徽章:
0
发表于 2012-02-21 14:13 |显示全部楼层
你要用个循环把所有数据都写到发送缓冲区去,但是套接口不保证你写到缓冲区里的数据都能送的出去

retval = write(sd, buffer+bytes_written, len);
这哪里来的代码

论坛徽章:
0
发表于 2012-02-21 14:15 |显示全部楼层
http://ishare.iask.sina.com.cn/f/11173186.html
这本书中  31 页。

作者应该不是这个意思。

论坛徽章:
0
发表于 2012-02-24 22:55 |显示全部楼层
jeung 发表于 2012-02-21 14:13
你要用个循环把所有数据都写到发送缓冲区去,但是套接口不保证你写到缓冲区里的数据都能送的出去

retval ...

《unix网络编程》中有讲,由于socket是低速IO设备,套接口不保证你想写要到内核缓冲区等于实际写入的字节数。write(sockfd, buff, 32),这句希望这次调用写入32字节,可能内核缓冲区已经没办法核收这么多了,可能只写入了5字节。你要保证你希望写入的字节数,那么你等多次调用write,至到写入你想写入的字节为止。write在出错的时候返回-1,调用成功但并没有写入数据返回0,大于0表示实际写入的字节数。《unix网络编程》中作者写了一个writen函数,用write实现,,writen可能多次调用write实现一次写入想写的字节,你可以在网上找到源代码,有人说,里面的代码就是可以拿来就用的。

PS:最好看这些经典的书吧,收获不少,很多疑问都可以解开(你可能会有更多疑问)。

论坛徽章:
0
发表于 2012-02-24 23:00 |显示全部楼层
本帖最后由 _print 于 2012-02-24 23:00 编辑

你的write是不是第二个参数写错了,还有,我看了你的while循环,它就是我上面说的writen函数做的工作,只是Steven把它封装成函数了,而这里的作者写到代码中,你喜欢那种风格由你了。我觉得Steven的方式更好,不要再来理解一次这个while的作用。

论坛徽章:
0
发表于 2012-02-25 14:16 |显示全部楼层
回复 5# _print


第二个参数没有写错,错的是第三个。 应该是len-bytes_written.

而这里我想知道的是,当使用write , 如果socket buffer 中的空间不足, write 是不是会立即返回还是会阻塞。 现在看来是前者。  而对于这种循环调用wirte 来完成写 本身也不算好注意。  如果socket buffer 一直没有 空闲空间, 或者在每次循环的这段间隔刚好空出来1bytes, 那么while 就要 100 次了?  更好的做法最好是能event drive 的。

关于
The second instance does not have that limitation, because FILE* has its own data-buffering subsystem. When you write to a FILE* buffer, the subsystem forces you to wait until it sends all the bytes.

不知道是不是有什么event drive, 至少不会比 wirte 差。

论坛徽章:
0
发表于 2012-02-25 14:41 |显示全部楼层
Meets 发表于 2012-02-25 14:16
回复 5# _print


你提的这种极端情况,基本是不存在的,一般都是上面说的这样处理。对一般socket进入简单的写,还不至于有什么问题。如果你真要用event drive那么你看看select,poll,epoll函数吧,就是你想要的,这些函数一般都是用在对大量socket对进操作的时候,杀鸡用牛刀。

论坛徽章:
0
发表于 2012-02-25 14:51 |显示全部楼层
Meets 发表于 2012-02-25 14:16
回复 5# _print


这段英文的意思是说,如果用FILE也就是C语言的I/O库函数操作,就不会有上面的问题,因为FILE会为你处理缓冲。可是Steven说这样会引入更隐蔽,更复杂的问题,你要了解请参考《unix网络编程》。我手里只有中文版,从你发英文看来,讲得完全一样,而看代码,却不是同一本书,不知谁抄谁的,天下文章一大抄。往往是最经典的书把该讲都讲得差不多了,其他人就东抄抄西抄抄,就出书,特别是国内作者,以前我只要一看到是国内出的书,就不看了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP