read()函数:
简介
read函数用于用于从文件描述符对应的文件读取数据(从打开的设备或文件中读取数据)。
文件描述符是Linux下的叫法,相当于windows下的句柄,socket建立后操作系统会分配一个文件描述符(相当于建立的socket的id)
使用
函数原型:ssize_t read(int fd,void*buf,size_t count)
几个参数分别代表:
fd:socket的文件描述符
buf:存放读出的数据的缓冲区
count:每次读取的最大字节数
返回值
读取成功返回读出的字节数,失败返回-1
堵塞的情况
在调用read函数过后,程序就会一直去接收缓存里面拿消息,如果没有消息发送过来,那么程序就会一直堵塞在read函数处等待消息的到来,也不会去执行后面的代码,除非对面发送了消息或者关闭了socket连接(其实关闭连接相当于也是发送了FIN消息过来),那么程序将会继续执行后续的操作。
注意点
因为read函数在收到一次消息后就会继续执行后续代码,那么可能存在两种情况,让程序没法收齐消息:
- 发送的消息长度超过了read()的第三个参数(即读取的最大字节数),这个时候也只会读到最大长度的消息,再往后的消息就不会再读取了。
- 报文太长,分包发送或者对方发了几次包,前面的包到了后面的包还没到,然后read()函数也执行完了就不再去read了。
基于上述两点,在调用read时一般会用while来反复read,如下所示:
while ((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0)
{
/* code */
}
这样,程序就会一直在接收缓存里面读消息,这时候除非另外一边close了socket(或出现了异常情况返回了-1),那么程序将从while循环里面跳出执行后续操作。这样就保证了每次的消息都能够正常读取完。