数据的IO和复用
网络数据能够正常的到达用户,并被用户接受网络数据传输的目的。网络数据的接受以及发送有多种方案,例如直接接受或者发送数据通过向量发送接受数据,通过消息进行接受以及发送。
1.介绍主要的常用的IO函数
2。介绍几种常用的IO模型
3 介绍select和pselect函数,如何利用这两个文件的描述符号进行文件读写描述符的监视。
4.简单的介绍函数poll和ppoll含义使用以及区别
5 以简单的例子介绍非堵塞编程。
-------------------------------------------------- IO 函数 -----------------------------------------------
recv函数用于接受数据,函数的原型如下。recv函数从套接字s中接受数据放到缓冲区buf中,buf的长度为len,操作的方式由flag决定。第一个参数s是套接字文件的描述符,它是由函数socket()返回的,第二个参数buf是一个指针,指向接受网络套接字的缓冲区,第三个参数表示缓冲区的大小,以字节为单位。
#include <sys/type.h>
#include <sys/socket.h>
ssize_t recv(int s,void * buf,size_t len,int flags);
flags的值以及含义
MSG_DONTWAIT 非阻赛的操作,立刻返回不等待
MSG_ERRQUEUE 错误消息从套接字错误队列接收
MSG_OOB 接收外数据数据
MSG_PEEK 查看数据,不进行数据缓冲区的清空
MSG_TRUNC 返回所有的数据,及时指定缓冲区过小
MSG_WAITALL 等待所有的消息
MSG_DONTWAIT:这个标志将单个IO操作设为非堵塞方式,而不需要在套接字上打开非堵塞的标志,执行IO操作。然后关闭非堵塞的标志。
MSG_ERRQUEUE: 改错误的传输依赖于所使用的协议。
MSG_OOB :这个标志可以接收带外数据,而不接收一般的数据。
MSG_PEEK : 这个标志用于查看可读数据,在recv函数执行后,内核不会将这些数据丢弃掉。
MSG_TRUNC: 在接收数据后,如果用户的缓冲区大小不足以完全复制缓冲区的数据,则将数据折断,仅复制用户缓冲区大小的数据,多余的数据将会舍弃掉。
MSG_WAITALL:这个标志告诉内核在没有读到请求的字节数之前不使读操作返回。如果系统支持使用这个标志,可以去掉readn()函数而使用下面的代替
#define readn(fd,ptr,n) recv(fd,ptr,n,MSG_WAITALL)
即使设置MSG_WAITALL,如果发生以下情况(a)捕获一个信号(b)连接终止(c)在套接字上发生了错误,这个函数返回的字节数依然会比请求的少。当指定MSG_WAITALL标志时,函数会复制与用户指定长度相等的数据。如果内核中的当前数据不能满足要求,会一直等待直到数据足够才返回。
函数recv()的返回值是成功接收到的字节数。当返回-1时错误发生,可以查看errno获取错误码,当另一个访民啊使用close()关闭连接时,返回值为0;
常见的错误码如下:
EAGAIN 套接字定义为非堵塞,而操作采用了堵塞的方式,或者定义的超时时间已经达到却没有接收到数据。
EBADF 参数s不是合法的描述符
ECONNREFUSED 远程主机不允许此操作
EFAULT 接受缓冲区指针在此进程之外
EINTR 接收到中断信号
EINTVAl 传递了不合法的参数
ENOTCONN 套接字s表示流式套接字,此套接字没有连接。
ENOTSOCK 参数不是套接字描述符
recv()函数通常用于TCP类型的套接字。UDP使用recvfrom()函数接受数据,当然在数据包套接字绑定地址一节端口号后,也可以使用recv()接受数据。
recv()函数 从内核的接收缓冲区复制到数据到用户指定的缓冲区。当内核的缓冲区比指定的缓冲区小时,一般情况下(没有采用MSG_WAITALL标志)会复制缓冲区的所有的数据到用户缓存区。并返回数据的长度。当内核的接收的缓冲区的数据比用户指定的多时,会将用户指定长度的len的接收缓冲区的数据复制到用户指定地址。其余的数据需要下次调用该函数时在复制,内核在复制用户指定的数据之后,会销毁已经复制完毕的数据,并进行调整。
使用send()函数发送数据
send()函数用于发送数据,函数的原型如下
#include<sys/types.h>
#include <sys/socket.h>
ssize_t send(int s,const void * buf,size_t len,int flags)
send()函数将缓冲区buf大小为len的数据。通过套接字文件描述符按照flags指定的方式发送出去,其中的参数含义与recv中的含义一致,它的返回值是成功的字节数,用于用户的缓冲区buf中的数据在通过send()函数进行发送的时候,并不一定能够全部发送出去,所以要检查send() 函数的返回值,按照与计划发送的字节长度是否相等来判断下一步的操作。
当send()函数的返回值小于len的时候,表明缓冲区仍然由部分数据没有成功的发送,这时需要重新发送剩余的部分,通常剩余数据发送的方法是对原来的buf中的数据位置进行偏移,偏移的大小为已经成功发送的字节数。
send 函数错误吗如下:
函数send()只能用于套接字处于连接状态的描述符,之前必须使用connect()函数或者其它函数进行连接。对于send()函数和write()函数之间的差别表示发送方式的flag,当flag为0时,send()函数和write()函数完全一致,而且send(s,buf,len,flags)与sendto(s,buf,len,flags,NULL,0)等价的。
网友评论