-
Notifications
You must be signed in to change notification settings - Fork 0
ibychance/swnet-linux
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
1. Recv-Q 大于 0, 表示有数据堆积, recv 不够及时,这种情况下的下一个收帧行为:UDP收取sendto的指定长度, TCP尽可能收取recv指定的长度, 需要应用层解包 2. Send-Q 大于 0, 只存在于异步描述符的情况, 同步描述符一定会等到缓冲区刷出后才返回 3. UDP的Recv-Q大于0, 甚至满了, 也不会导致发送端的Send-Q堆积, 这个情况下的后果就是:丢帧 使用非阻塞 connect 需要注意的问题是: 1. 很可能 调用 connect 时会立即建立连接(比如,客户端和服务端在同一台机子上),必须处理这种情况。 2. Posix 定义了两条与 select 和 非阻塞 connect 相关的规定: 1)连接成功建立时,socket 描述字变为可写。(连接建立时,写缓冲区空闲,所以可写) 2)连接建立失败时,socket 描述字既可读又可写。 (由于有未决的错误,从而可读又可写) 不过我同时用epoll也做了实验(connect一个无效端口,errno=110, errmsg=connect refused),当连接失败的时候,会触发epoll的EPOLLERR与EPOLLIN,不会触发EPOLLOUT。 当用select检测连接时,socket既可读又可写,只能在可读的集合通过getsockopt获取错误码。 当用epoll检测连接时,socket既可读又可写,只能在EPOLLERR中通过getsockopt获取错误码。 /* * 触发条件: * 1. 有数据到达 * 2. 有 syn 请求到达 * 3. 读取缓冲区因任意可能转变为非空 * TCP 读缓冲区 cat /proc/sys/net/ipv4/tcp_rmem * * 备注: * 1.9系列版本的最大特色就是epoll线程直接处理描述符的数据 * 2.描述符从epoll唤醒到上层分析协议总共经历以下步骤: * 2.1 响应epoll事件,从内核缓冲区read直到EAGAIN * 2.2 应用层解包 * 2.3 等待上层处理完成 * 这其中,2.1和2.2, 无论是否转换线程,需要的计算时间都是相同,8系列的处理方式画蛇添足 * 转换线程尽管可以表面上促进epoll获得下一个描述符事件,但收到事件后的处理消耗CPU时间并不会减少 * 唯一需要关注的上层应用在 on_recvdata 中的操作方案, 如果上层采用耗时操作, 则会阻塞当前线程上所有描述符的继续收包 * 3.考虑到多数的快速响应案例,即便上层可能发生阻塞操作,也应该由上层投递线程池,而不是由下层管理线程池 */ if (evts[i].events & EPOLLIN) { if (ncb->ncb_read) { if (ncb->ncb_read(ncb) < 0) { nis_call_ecr("[nshost.io.__iorun] ncb read function return fatal error, this will cause link close, link:%lld", hld); objclos(ncb->hld); } }else{ nis_call_ecr("[nshost.io.__iorun] ncb read function unspecified,link:%lld", hld); } } /* * EPOLLOUT检查异步连接的返回状态 * 因为epoll本身没有明确提出当异步connect成功之后会返回什么样的信号,通过测试有如下结果: * 1,当本地还没调用connect函数,却将套接字送交epoll检测,epoll会产生一次 EPOLLOUT | EPOLLHUP, 也就是产生一个值为0x14的events. * 2,当本地connect事件发生了,但建立连接失败,则epoll会产生一次 EPOLLIN | EPOLLERR | EPOLLHUP, 也就是一个值为0x19的events. * 3,当connect函数也调用了,而且连接也顺利建立了,则epoll会产生一次 EPOLLOUT, 值为0x4,即表明套接字已经可写。 */ /* * ET模式下,EPOLLOUT触发条件有: * 1.缓冲区满-->缓冲区非满; * TCP 写缓冲区 cat /proc/sys/net/ipv4/tcp_wmem * 2.同时监听EPOLLOUT和EPOLLIN事件 时,当有IN 事件发生,都会顺带一个OUT事件; * 3.一个客户端connect过来,accept成功后会触发一次OUT事件。 * 4.通过 EPOLL_CTL_MOD 增加 EPOLLOUT 的关注, 立即得到一个OUT事件(不管缓冲区状态), 已经关注EPOLLOUT重复调用epoll_ctl则不会立即得到事件 * * 注意事项: * 1. (EPOLLIN | EPOLLOUT) 一旦被关注, 则每个写入缓冲区不满 EPOLLIN 都会携带触发一次, 损耗性能, 且不容易操作 oneshot * 2. 平常无需关注 EPOLLOUT * 3. 一旦写入操作发生 EAGAIN, 则下一个写入操作能且只能由 EPOLLOUT 发起(关注状态切换) * * * 已验证:当发生发送EAGAIN后再关注EPOLLOUT,可以在缓冲区成功空出后得到通知 */ if (evts[i].events & EPOLLOUT) { wp_queued(ncb->hld); } /* * 组播报文的目的地址使用D类IP地址, D类地址不能出现在IP报文的源IP地址字段。单播数据传输过程中,一个数据包传输的路径是从源地址路由到目的地址,利用“逐跳”的原理[路由选择]在IP网络中传输。 * 然而在ip组播环中,数据包的目的地址不是一个,而是一组,形成组地址。所有的信息接收者都加入到一个组内,并且一旦加入之后,流向组地址的数据立即开始向接收者传输,组中的所有成员都能接收到数据包。 * 组播组中的成员是动态的,主机可以在任何时刻加入和离开组播组。 * 用同一个IP多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。 * 此外,不属于某一个多播组的主机也可以向该多播组发送数据包。 * * 组播地址 * 组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。 * 永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。 * 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用 * 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet * 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效 * 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效 * * 组播是一对多的传输方式,其中有个组播组的 概念,发送端将数据向一个组内发送,网络中的路由器通过底层的IGMP协议自动将数据发送到所有监听这个组的终端。 * 至于广播则和组播有一些相似,区别是路由器向子网内的每一个终端都投递一份数据包,不论这些终端是否乐于接收该数据包。UDP广播只能在内网(同一网段)有效,而组播可以较好实现跨网段群发数据。 * UDP组播是采用的无连接,数据报的连接方式,所以是不可靠的。也就是数据能不能到达接受端和数据到达的顺序都是不能保证的。但是由于UDP不用保证数据 的可靠性,所有数据的传送效率是很快的。 */ int udp_joingrp(HUDPLINK link, const char *ipstr, uint16_t port)
About
network programing simple framework for POSIX
Resources
Stars
Watchers
Forks
Packages 0
No packages published