C语⾔socket编程中关于read()和write()的思考
最近开始学习C的socket编程,教材上有⼀处依照我对IO函数的理解,我感觉有点问题,故⽽研究了⼀下。学的很浅,可能有错漏。1.socket编程中read()和write()内部原理
每个socket应该是在内核中具有相应的send_buffer和recv_buffer,这个就是普通⽂件读写中常说的内核缓冲,应该⼤致是⼀样的。以下的讨论均基于阻塞模式下,实际可以设置为⾮阻塞模式,但暂还没详细研究。
read()
如果recv_buffer中有数据,则read()将数据从recv_buffer拷贝到⽤户态buffer(read的参数之⼀)中,返回;
如果recv_buffer中没有数据,则read()阻塞;
write()
如果send_buffer剩余空间⾜以容纳相应数据,则write()将数据从⽤户态buffer拷贝到send_buffer中,返回;
如果send_buffer剩余空间不⾜以容纳相应数据,则write()阻塞;
2.发送⽅和接收⽅交接问题
类⽐到硬盘,可以将发送⽅的send_buffer理解成接收⽅的recv_buffer;
tcp传输不存在数据边界的特点,有可能发送⽅将msg使⽤1次write()就写⼊了send_buffer,但是可能分3次才能完全传输到接收⽅的recv_buffer中,然后由于有数据就会读取并返回的特点,接收⽅应该调⽤3次read();
造成的问题就是,tcp的接收⽅根本不知道到底要分⼏次才能完全接收发送⽅ write()的内容,因为⼀次write()也可能分成⼏个包先后传输到接收⽅的recv_buffer中,就仿佛发送⽅调⽤好⼏次write()⼀样。因此接收⽅应该利⽤while循环不断进⾏读取,才能确保已经将某次发送⽅send**的内容完全读取了;
书中说server可能接受到client多次write()的结果,我认为是有问题的,可能是翻译错误或者笔误;
其实理解这个问题⽽⾔,可以忽略底层的tcp传输具体细节,单就理解作为端点的send_buffer和recv_buffer,其更新是⾮同步的,时间⾜够后才会⼀致;
3.问题代码分析
client:
write(clntSock, message,strlen(message));
str_len =read(clntSock, message, BUF_SIZE -1);
server:
while((strLen =read(accSock, msgBuf, BUF_SIZE))!=0)
c语言和c++区别{
write(accSock, msgBuf, strLen);
}
具体的执⾏情况为:
1. Clinet:调⽤write()将数据写⼊send_buffer,read()因为recv_buffer为空阻塞;
2. Client:⼀段时间后,内核将send_buffer中数据分N次发送到server的recv_buffer中;
3. Server:read()阻塞,直到recv_buffer不为空便⽴刻读取到⽤户态的msgBuf中,不管此时有多少数据和是否完整;
4. Server:调⽤writer()将read()获取的数据写⼊到send_buffer中;
5. Server:将send_buffer中数据传输到client的recv_buffer中,有可能client调⽤write()发送的数据被分成N份发送到了server中,到client检测到有recv_buffer有数据时,只返回了M份;
6. Client:调⽤read()读取到⽤户态的msgBuf中,由于5中的原因,这次读取到内容可能只有调⽤write()发送数据中的M/N;
程序本⾝的需求是实现回声服务器,输⼊字符串,server将client发送的字符串完整地返回,然后client接受并输出相同的字符串。依据上⾯的执⾏情况分析,明显不能满⾜。具体的原因为每次循环中,client只调⽤⼀次read(),然后就直接输出。
于是应该修改为:
client:
int send_size, recv_size, recv_cnt;
send_size =strlen(message)
recv_size =0;
write(clntSock, message,strlen(message));
while(recv_size < send_size)
{
recv_cnt =read(clntSock, message, BUF_SIZE -1); if(-1== recv_cnt)
exit(1);
recv_size += recv_cnt;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论