第九讲高级socket编程

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
Both return: number of bytes read or written, –1 on error
采用 select 等待连接建立, 设置时间限制, 减少等待时间
通常connect的超时从 75 秒到几分钟. 如果不想等那么长时间, 那就有必要采用nonblocking
ቤተ መጻሕፍቲ ባይዱ
Nonblocking connect 代码
见 unpv103e/lib/connect_nonb.c 框架要点:
设置NONBLOCKING 尝试 connect 设置 select 参数,select 监听
网络化编程
第九讲 高级socket编程
内容提要
高级IO函数 Nonblocking IO 信号驱动IO Unix domain socket Raw socket
高级IO函数
read/recv/readv/recvmsg write/send/writev/sendmsg
recvmsg/sendmsg最为通用,可以替代所有的 其它函数
read/write最简单,并且不限于socket
recv/send 函数
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);
MSG_PEEK 标志
允许程序检查有多少数据可读 不同于recv/recvfrom的是,数据仍然存放在
socket缓冲区内
MSG_WAITALL 标志
指示内核只有当指定数目的字节读取完毕,read才能够 返回
readn 函数可以采用下面的宏代替 :
#define readn(fd, ptr, n) recv(fd, ptr, n, MSG_WAITALL)
Accept: Blocking vs. nonblocking
accept 就是应用程序从内核的连接队列中取出 一个ESTABLISHED连接【回忆】
Blocking accept
如果有ESTABLISHED连接,返回之;否则,阻塞
Nonblocking accept
如果没有,立即返回,指示错误EWOULDBLOCK
SIGALRM句柄的设置与恢复信号 alarm的设置与恢复
TCP SOCKET
Nonblocking read/write
STDIN STDOUT
Echo client例子
采用select多路复用机制 见 unpv103e/nonblock/strclinonb.c
比较完整,综合考虑读、写阻塞 考虑框架 + 逻辑(Logic)
const int on = 1;
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) error…
Raw Socket Creation
int sockfd;
sockfd = socket(AF_INET, SOCK_RAW, protocol);
输入 read, readv, recv, recvfrom, and recvmsg
输出 write, writev, send, sendto, and sendmsg
接受连接请求 accept 连接请求 connect
Blocking read vs. nonblocking read
Family:AF_UNIX/AF_LOCAL See unpv103e/unixdomain/unixbind.c
struct sockaddr_un { sa_family_t sun_family; /* AF_LOCAL */ char sun_path[108]; /* null-terminated pathname */
Both return: number of bytes read or written if OK –1 on error
常见的 flags
MSG_DONTWAIT 标志
对一个单独的 I/O 操作设定 nonblocking 模式, 不必针对整个 socket
该 I/O 操作结束后, 自动关闭 nonblocking 模式
操作).
readv/writev 函数
#include <sys/uio.h>
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
框架 + 逻辑
内部逻辑:
记录多个WEB对象及TCP连接(状态) 状态转移
信号驱动IO
SIGIO RT Signal
SIGIO 信号的发生条件
SIGIO with UDP Sockets
socket上有一个数据报文到达 Socket上发生一个异步错误
SIGIO with TCP Sockets
Blocking read
TCP, 如果没有数据,阻塞;如果哪怕有一个Byte的 数据,可以返回,除非设置了MSG_WAITALL标志
UDP,如果没有报文到达,阻塞;有一个报文到达, 返回
Nonblocking read
如果有数据,返回;否则,立即返回,指示错误 EWOULDBLOCK
Blocking write vs. nonblocking write
Connect: Blocking vs. nonblocking
connect 的任务是完成三次握手 Blocking connect
如果三次握手没有完成,阻塞等待完成 否则返回
Nonblocking connect
如果三次握手没有完成,立即返回,指示错误
EINPROGRESS
Socket Timeouts
struct iovec { void *iov_base; size_t iov_len;
};
/* address of buffer */ /* size of buffer */
iov 指向一个 iovec 结构数组,IOV_MAX 定义最大数组长度
Nonblocking IO
By default, sockets are blocking blocking socket 操作
在监听 socket上有一个连接请求完成 连接拆卸请求启动 连接拆卸请求完成 半连接关闭shutdown Socket上有数据到达 Socket上有数据发送 (i.e., 输出缓冲区有空间) 有异步错误发生
RT signal - 实时信号
Why RT signal?
信号驱动 I/O 处理多个连接时有些问题, 程序无法 知道是哪个socket有事件到达.
Unix Domain socket
#include <sys/socket.h> #include <sys/un.h>
unix_socket = socket(PF_UNIX, type, 0); error = socketpair(PF_UNIX, type, 0, int *sv);
Unix Domain Address
缓冲区管理
Nonblocking connect
三次握手时间
一个connect 需要花费一个 RTT 的时间 RTT时间可能在几ms(LAN)到几百ms 甚至几秒(WAN)之间 Server busy
采用nonblocking connect,多个连接建立过程可以同时 进行.
这在 Web browsers中非常常见.
POSIX 实时信号 (RT signals) 比较 SIGIO做了重大 改进
首先, 允许一个信号和一个描述符关联 其次, 信号在内核排队, 实现事件驱动的机制 但是, 这个队列可能溢出, 这时可能还需要 SIGIO.
Unix Domain socket
一种IPC机制,只能用于本机的进程之间通信. 两种类型:Stream、Datagram 可以用于进程之间传递文件描述符
同时监视socket的可读、可写状态
成功 or 超时?
Nonblocking connect - Web client
模拟真实的浏览器
阻塞取第一个HTML页面,然后 可以启动n 个并发 TCP连接取WEB对象
见 unpv103e/nonblock/
web.c, web.h, home_page.c, start_connect.c, write_get_cmd.c
};
sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); unlink(argv[1]); /* OK if this fails */ bzero(&addr, sizeof(addr)); addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, sockname, sizeof(addr.sun_path) - 1); bind(sockfd, (SA *) &addr, SUN_LEN(&addr));
的源 IP 地址 (但 IP_HDRINCL socket 选项设置后 会不同). 如果没有 bind, 内核选择源 IP 地址.
即便指定了 MSG_WAITALL, read仍然可能返回少于指定 数目的数据: a signal is caught the connection is terminated an error is pending for the socket.
readv/writev 函数
#include <sys/uio.h>
Blocking write
TCP,写操作相当于将应用程序的数据拷贝到内核 的socket send缓冲区。
如果send缓冲满,操作阻塞; 否则,返回实际拷贝的数据长度(可能比预期的短)
UDP,不会阻塞
Nonblocking write
TCP,如果send缓冲区满,立即返回,指示错误 EWOULDBLOCK
Protocol
IPPROTO_xxx, 定义在 <netinet/in.h> 中, 比如 IPPROTO_ICMP.
只有root 可以创建 raw socket
Bind, connect
raw socket可以bind, 但很少见.
只设置本地IP地址: raw socket 下没有端口的概念 对发送而言, bind 设置了raw socket上发送的分组
采用alarm
采用信号
IO多路复用 select
可以管理多个file descriptor 可以精确到微秒
SO_RCVTIMEO 和 SO_SNDTIMEO socket 选项
新的选项,仅限于socket 可以精确到微秒
alarm例子
参见 unpv103e/lib/connect_timeo.c 要点:
readv/writev 函数
通用,不限于socket 类似于 read / write, 但 readv / writev 允许一次
调用读/写多个缓冲区 这些操作习惯被称为
scatter read (因为input被分散到多个应用程序缓冲区) gather write (因为多个缓冲区数据被收集到一个输出
Raw Socket
提供正常TCP 、UDP socket 不具备的功能
read / write ICMPv4, IGMPv4, ICMPv6 packets read / write IPv4 分组
处理内核不理解的 IPv4 协议分组
创建自己的 IPv4 头部
使用 IP_HDRINCL socket option
相关文档
最新文档