<em id="1rarx"><ins id="1rarx"></ins></em><sup id="1rarx"></sup>

<progress id="1rarx"><tr id="1rarx"></tr></progress>
<sup id="1rarx"><menu id="1rarx"></menu></sup>
<menuitem id="1rarx"></menuitem><optgroup id="1rarx"><small id="1rarx"><sub id="1rarx"></sub></small></optgroup>

    <sup id="1rarx"><menu id="1rarx"></menu></sup>
    <div id="1rarx"></div><div id="1rarx"><tr id="1rarx"><object id="1rarx"></object></tr></div>
      <em id="1rarx"></em>

          存档

          ‘网络编程’ 分类的存档

          TCP连接建立的三次握手与连接断开四次挥手

          2017年9月4日 没有评论

          TCP三次握手

          一、什么是三次握手

          三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。

          二、三次握手的目的

          三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。客户端执行连接请求时。将触发三次握手。

          三、三次握手过程

          第一次握手:
          客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。
          第二次握手:
          服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的ISN加1以.即X+1。
          第三次握手.
          客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1。如果正确则连接建立成功,客户端和服务器进入ESTABLISHED状态,完成三次握手,随后客户端与服务器之间可以开始传输数据了。把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1。

          TCP四次挥手

          一、什么是四次挥手

          TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,任?#25105;?#26041;执行close操作即可产生挥手操作。

          二、四次挥手过程

          第一次挥手:

          客户端发送一个FIN,用来关闭客户端到服务器的数据传送,客户机进入FIN_WAIT_1状态。
          第二次挥手:

          服务器收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务器进入CLOSE_WAIT状态。
          第三次挥手:

          服务器发送一个FIN,用来关闭服务器到客户端的数据传送,服务器进入LAST_ACK状态。
          第四次挥手:

          客户端收到FIN后,客户端进入TIME_WAIT状态,接着发送一个ACK给服务器,确认序号为收到序号+1,服务器进入CLOSED状态,完成四次挥手。

          有限状态机FSM:Finite State Machine
          1、CLOSED 没有任何连接状态
          2、LISTEN 侦听状态,等待来自远方TCP端口的连接请求
          3 、SYN-SENT 在发送连接请求后,等待对方确认
          4、SYN-RECEIVED 在收到和发送一个连接请求后,等待对方确认
          5、ESTABLISHED 代表传输连接建立,双方进入数据传送状态
          6、FIN-WAIT-1 主动关闭,主机已发送关闭连接请求,等待对方确认
          7 、FIN-WAIT-2 主动关闭,主机已收到对方关闭传输连接确认,等待对方发送关闭传输连接请求
          8、 TIME-WAIT 完成双向传输连接关闭,等待所有分组消失
          9、CLOSE-WAIT 被动关闭,收到对方发来的关闭连接请求,并已确认
          10、LAST-ACK 被动关闭,等待最后一个关闭传输连接确认,并等待所有分组消失

          11、CLOSING 双方同时尝试关闭传输连接,等待对方确认

          附加问题:

          【问题1】为什么连接的时候是三次握手,关闭的时候却是四次挥手?
          答:因为当服务器收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来回应的,SYN报文是用来同步的。但是关闭连接时,当服务器收到FIN报文时,很可能并?#25442;?#31435;即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,”发送的FIN报文已经收到”。只有等到客户端所有的报文都发送完了,客户端才能发送FIN报文,因此不能一起发送。故需要四步挥手。
          【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
          答:四个报文都发送完毕,客户端和服务器可以直接进入CLOSE状态了,但有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文,确保之前的数据?#25442;?#20002;失后再进入close状态。

          原文:http://www.178linux.com/85976

          分类: 网络编程 标签:

          epoll入门实例

          2016年4月10日 没有评论

          epoll是目前进行服务器端编程的普遍选择,好处很多,这里不再赘述,本文主要描述如何在c语言中使用epoll的完整样例程序。
          首先介绍用到的数据结构和三个api说明,然后通过编写一个打印所有输入到socket的字符输出到终端的服务器端的程序来完成整个例?#21360;?/p>

          epoll_event是用来对要监控的socket描述, 它包括epoll_data_t和要监控的?#24405;?#31867;型的(一个__uint32_t类型的events)。epoll_data_t里的fd是用来存储要监控的文件描述符。

          events 结构体中第一个参数支持的?#24405;?#31867;型

          – EPOLLIN,读?#24405;?/p>

          – EPOLLOUT,写?#24405;?/p>

          – EPOLLPRI,带外数据,与select的异常?#24405;?#38598;合对应

          – EPOLLRDHUP,TCP连接对端至少写?#31383;?#20851;闭

          – EPOLLERR,错误?#24405;?/p>

          – EPOLLET,设置?#24405;?#20026;边沿触发

          – EPOLLONESHOT,只触发一次,?#24405;?#33258;动被删除

          epoll在一个文件描述符上只能有一个?#24405;?#22312;一个描述符上添加多个?#24405;?#20250;产生EEXIST的错误。同样,删除epoll的?#24405;?#21482;需描述符就够了

          使用epoll的三个api
          头文件 /usr/include/sys/epoll.h
          1. 生成一个epoll专用的文件描述符
          如果调用成功返回0,不成功返回-1

          epoll_create返回的是一个文件描述符,也就是说epoll是以特殊文件的方式体?#25351;?#29992;户
          __size提示操作系?#24120;?#29992;户可能要使用多少个文件描述符,该参数已经废弃,填写一个大于0的正整数

          2.用于控制某个文件描述符上的?#24405;?#21487;以注册?#24405;?#20462;改?#24405;?#21024;除?#24405;?br /> 如果调用成功返回0,不成功返回-1

          3.用于轮询I/O?#24405;?#30340;发生,返回发生?#24405;?#25968;

          epoll的api使用方式
          1.epoll_create 生成的epoll专用的文件描述符
          2.使用epoll_ctl注册?#24405;?#20462;改?#24405;?#21024;除?#24405;?#23545;应的文件描述符到epollfd指定的epoll内核?#24405;?#34920;中
          3.使用epoll_wait阻塞等待注册的文件描述符上可读?#24405;?#30340;发生
          4.当有新客户端的连接或者客户端的数据写入,返回需要处理的?#24405;?#25968;目

          epoll的两种模式

          1. 水平触发(LT):使用此种模式,当数据可读的时候,epoll_wait()将会一直返回就绪?#24405;?#22914;果你没有处理完全部数据,并?#20197;?#27425;在该epoll实例上调用epoll_wait()才监听描述符的时候,它将会再次返回就绪?#24405;?#22240;为有数据可读。ET只支持非阻塞socket。

          2. 边缘触发(ET):使用此种模式,只能获取一次就绪通知,如果没有处理完全部数据,并?#20197;?#27425;调用epoll_wait()的时候,它将会阻塞,因为就绪?#24405;?#24050;经?#22836;?#20986;来了。

          ET的效能更高,但是对程序员的要求?#21754;?#39640;。在ET模式下,我们必须一次?#21024;?#32780;彻底地处理完所有?#24405;T两种模式的socket都支持。

          实例代码

          1.创建并绑定服务器端socket
          采用一种可移植的方式来生产socket,getaddrinfo返回对应的网卡信息,遍历对应的网络接口生成socket
          成功返回socket文件描述符,失败返回-1

          2.设置socket为非阻塞模式
          通过在文件描述符上设置 O_NONBLOCK 表识来实现非阻塞socket

          3.event 循?#21453;?#29702;

          main函数的流程是
          1. create_and_bind创建服务器端的socket描述符
          2. 设置描述符为非阻塞
          3. 监听描述符
          4. 创建epoll文件描述符efd
          5. 使用边缘触发的方式添加sfd输入监听?#24405;?/p>

          最外层的while循环时主?#24405;?#24490;环(event loop)。调用epoll_wait阻塞等待?#24405;?#21457;生,当?#24405;?#21040;达epoll_wait返回?#24405;?#22312;?#24405;?#21442;数中,一批epoll_event结构体。
          epoll?#24405;?#24490;?#20998;衑poll实例在建立新连接时候添加?#24405;?#21644;当断开连接的时候删除?#24405;?/p>

          当?#24405;?#21457;生时,有如?#24405;?#31181;方式
          错误:当发生错误,或者不是可读?#24405;?#36890;知时,简单关闭文件描述符,关闭文件描述符会自动从efd的监控集中删除。
          新连接:当监听描述符可读时,表示有新的连接到达,accept()新连接,设置新连?#29992;?#36848;符为非阻塞并添加到efd监控集中。
          客户端数据:当任?#25105;?#20010;客户端文件描述符可读,使用read()每次读区512字节循环读取。 因为我们需要读取当前所有可读区数据 ,当边缘触发的情况下?#25442;?#20877;次通知可读。 读取到的数据调用write写到标准输出stdout (fd=1)。如果read(2)返回0,表示EOF并切可以关闭客户端连接。如果返回-1并且 errno设置为EAGAIN表示这个?#24405;?#25152;有可读的数据读取完毕可以返回进入主?#24405;?#24490;环。

          就这样不断的循环,添加和删除文件描述符到efd的监控集中。
          https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/

          分类: 网络编程 标签:

          区分同步 异步 阻塞 非阻塞

          2016年1月18日 没有评论

          同步/异步
          首先来解释同步和异步的概念,这两个概念与消息的通知机制有关.
          举个例子,比如我去银行办理业务,可以自己去排队办理,也可以叫人代办,等他帮忙处理完了直接给我结果,对于要办理这个银行业务的人而言,自己去办理是同步方式,而别人代办完毕则是异步方式.区别在于,同步的方式下,操作者主动完成了这件事情.异步方式下,调用指令发出之后,操作马上?#22836;?#22238;了,操作者并不能马上就知道结果了,而是等待所调用的异步过程(在这个例子中是帮忙代办的人)处理完毕之后,通过通知手段(在代码中通常是回调函数)来告诉操作者结果.
          异步IO
          在上图的异步IO模型中,应用程序调用完aio_read之后,不论是否有数据可读,这个操作都会马上返回,这个过程相当于这个例子中委托另一个人去帮忙代办银行业务的过程,当数据读完拷贝到用户内存之后,会发一个信号通知原进程告诉读数据操作已经完成(而不仅仅是有数据可读).

          阻塞/非阻塞
          接着解释阻塞/非阻塞的概念,这两个概念与程序处理事务时的状态有关.
          同样是前面的例子,?#38381;?#27491;执行办理业务的人去办理银行业务时,前面可能已经有人排队等候了.如果这个人一直从排队到办理完毕,中间都没有做过其他的事情,那么这个过程就是阻塞的,这个人当前只在做这么一件事情.
          阻塞IO
          在上图中,应用程序发起recvfrom操作之后,要等待数据拷贝成功才能返回,这一整个过程中,不能做其它的操作,这个就是典型的阻塞IO.

          反之,如果这个人发现前面排队的人不少,于是选择了出去逛逛,过了一会再回来看看有没有轮到他的号被叫到,如果没有又继续出去逛过一阵再回来看看,如此以往,这个过程就是非阻塞的,因为处理这个事情的人,在这整个过程中,并没有做到除了这件事之外不能再做别的事情,他的做法是反复的过来尝试,如果没有完成就下一次再次尝试完成这件事情.
          非阻塞IO
          上图与前面阻塞IO图示的区别在于,当没有数据可读时,同样的recvfrom操作返回了错误码,表示当前没有可读数据,换言之,即使没有数据也?#25442;?#19968;直让这个应用阻塞在这个调用上,这就是非阻塞IO.

          到了这里,可以先简单的小结一下这两组概念了:

          阻塞/非阻塞:区别在于完成一件事情时,是不是当事情还没有完成时,处理这件事情的人除此之外不能再做别的事情.
          同步/异步:是自己去做这件事情,还是等别人做好了来通知你做好了,然后自己去拿结果.注意,这里说的是拿结果.如果只是别人告诉你可以做某事,然后自己去操作,这种情况下也是同步的操作,在后面多路复用I/O中会进行阐述.

          可见,两组概念不是一个维度的概念.我们把需要办理银行业务的人称为A,把代办理的人称为B,那么在A委托B办理业务的情况下,假设A在交代B帮忙办事之后,A就去做别的事情了,那么A并不存在针对办理银行业务这件事情而言是阻塞还是非阻塞,办理事务时阻塞与否是针对真正需要办理这件事情的人,也就是这个例子里的B.

          与多路复用I/O的联系
          前几年写上一篇文章的时候,将多路复用I/O类的select/poll等和异步操作混为一谈,在这里需要特别做一些补充说明.在以前的说明中,就这个例子而言,我列举了一个情况,当去办理业务的人,需要排队时通常都会先去叫号拿到一个纸条上面写了号码,然后等待银行叫号,在那个例子里面,我将银行叫号比作select操作,把纸条比作向select注册的回调函数,一旦可以进行操作的条件满足,就会根据这个回调函数来通知办理人,然后办理人再去完成工作,因此select等多路复用操作是异步的行为.

          上面那个例子,最大的错误在于,没有意识到,同步与异步的区别在于是不是要求办理者自己来完成,所有需要自己去完成操作的都是同步操作,不管是注册了一个回调(这里的叫号小纸条)等待别人回调你,还是自己一直阻塞等待.在上面的例子中,虽然对需要办理业务的人而言,通过叫号小纸条,他可以等待银行的办理通知,等待的同时可以去做点别的事情,比如看看手机什么的,但是只要可以办理该业务的条件满足,真正叫到?#22235;?#30340;号可以办理业务时,办理者是需要自己去完成办理的.

          换言之,在完成一件事情时,这里需要区分处理两种状态:一是这个事情是不是可以做了(条件满足的消息,如select告诉你某个文件描述符可读),一是完成了这件事情(如调用read/write完成IO操作).多路复用IO做的,是它可以记录下来有哪些人在等待消息的通知,在条件满足时负责通知办理者,而完成这件事情还是需要办理者自己去完成.只要是自己去完成的操作,都是同步的操作.

          UNP的6.2节中,最后对异步/同步做的总结是最准确的了:

          POSIX defines these two terms as follows:

          A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
          An asynchronous I/O operation does not cause the requesting process to be blocked.
          Using these definitions, the first four I/O models—blocking, nonblocking, I/O multiplexing, and signal-driven I/O—are all synchronous because the actual I/O operation (recvfrom) blocks the process. Only the asynchronous I/O model matches the asynchronous I/O definition.

          http://www.codedump.info/?p=515

          分类: 网络编程 标签:
          印度快乐8官网
          <em id="1rarx"><ins id="1rarx"></ins></em><sup id="1rarx"></sup>

          <progress id="1rarx"><tr id="1rarx"></tr></progress>
          <sup id="1rarx"><menu id="1rarx"></menu></sup>
          <menuitem id="1rarx"></menuitem><optgroup id="1rarx"><small id="1rarx"><sub id="1rarx"></sub></small></optgroup>

            <sup id="1rarx"><menu id="1rarx"></menu></sup>
            <div id="1rarx"></div><div id="1rarx"><tr id="1rarx"><object id="1rarx"></object></tr></div>
              <em id="1rarx"></em>

                  <em id="1rarx"><ins id="1rarx"></ins></em><sup id="1rarx"></sup>

                  <progress id="1rarx"><tr id="1rarx"></tr></progress>
                  <sup id="1rarx"><menu id="1rarx"></menu></sup>
                  <menuitem id="1rarx"></menuitem><optgroup id="1rarx"><small id="1rarx"><sub id="1rarx"></sub></small></optgroup>

                    <sup id="1rarx"><menu id="1rarx"></menu></sup>
                    <div id="1rarx"></div><div id="1rarx"><tr id="1rarx"><object id="1rarx"></object></tr></div>
                      <em id="1rarx"></em>