linux学习之旅(26)-----网络编程基础

在上一篇文章Linux学习之旅(25)----网络协议中介绍了常用的几种网路协议的格式,这篇文章将简述网路的编程需要的知道的一些基础知识。

TCP的运输连接管理

TCP的连接和释放是每次面向连接的通讯中必不可少的过程。因此,运输连接就有三个阶段,即连接建立数据传输、和连接释放。运输连接的管理就是使运输的连接和释放都可以正常地进行。

TCP建立连接(三次握手)

在TCP建立连接的过程中需要解决以下3个问题:

(1)要使每一方能够知道对方的存在。

(2)要允许双方协商一些参数(如最大窗口值)

(3)能够对运输实体资源(如缓冲大小、连接表中的项目等)进行分配。

Tcp连接的建立采用客户服务器方式。主动发起连接建立的应用程序叫做客户(client),被动等待连接建立的应用程序叫做服务器(server)

(1)两个进程都处于CLOSED(关闭状态),服务器进程创建传输控制块(TCB),准备接收客户进程的连接请求。在服务器创建出TCB后,服务器就会进出LISTEN(监听状态),等待客户的连接请求。

(2)第一次握手:客户在连接服务器之前也需要先创建TCB,然后向服务器发送连接请求报文(即首部SYN=1,ACK=0的报文段),另外TCP规定在请求连接报文中SYN=1的报文端不能携带数据,但需要消耗掉一个序号(seq)。这时客户端进入SYN-SENT(同步以发送状态)

(3)第二次握手:服务在接收到客户端的连接请求报文后,如果同意建立连接,则向客户发送连接接受报文(SYN=1,ACK=1),同时将首部的确认字段的确认号置为x+1(表示x+1之前的数据已经全部正确接收,下一次期待从序号x+1开始发送报文),并将选择一个初始序列号seq=y。这时服务器进入SYN-RCVD(同步以接收状态)

(4)第三次握手:客户端在接收到服务器发送的连接接受报文后,会向服务器在发送一个确认报文(ACK=1),确认号ack=y+1,序号为x+1。TCP规定ACK报文段,可以携带数据,但如果不携带数据则不消序号。所以下一次客户端发送数据时的序号还是x+1。这时TCP连接已经成功建立,客户端进入ESTABLISHED(已建立连接状态)。服务在收到客户端的确认报文后,服务器也会进入已建立连接状态

以上就是TCP建立连接三次握手的过程。需要注意的是如果在第二次握手中,服务器先向客户端发送ACK确认报文(ACK=1,ack=x+1),然后再发送SYN同步报文(SYN=1,seq=y),这样就将三次握手的过程变为四次握手,但效果是一样的。

为什么客户端还要最后向服务器发送一个确认报文?

为了防止已失效的连接请求报文段突然又传到了服务器,而产生错误。假设客户端向服务器发送了一个连接请求报文,但是由于此时网络状态不好,导致这个连接请求长时间无法发送到服务器,。于是客户端再次给服务器发送了一个连接请求报文,这时服务成功的接收到了连接请求报文,并和客户端成功建立连接发送数据,在数据发送完毕之后,又正常的释放的连接。然后客户端发送的第一个连接请求终于发送到了服务器,此时服务器有和客户端再次建立起连接(因为连接不需要确认,所以再服务器确认后,连接就会成功建立),但客户端此时并没有向服务器发送建立连接的请求,所以就会或略服务器的确认,服务器就因此会一直等待,就会导致服务的资源浪费。所以需要客户端最后向服务器发送确认报文。

为什么TCP需要进行三次握手,不是两次那?

(1)防止已失效的连接请求报文段引发的错误。

(2)为了实现可靠的通信。

因为TCP是面向字节流的,所以为了实现可靠通讯,TCP在协议中增加了序号和确认号字段,序号的作用是用来传输数据中第一个字节的位置,而确认号是用来确认当前已经有哪些字节被成功接收,下一次期待开始接收第一个字节的序号。三次握手的过程就是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值(该值并不是从0开始的,而是由发送方随机选择的)的过程,如果只有两次握手的话,那么服务器的序号将不能被确认,就会导致通信不安全。

TCP连接释放(四次挥手)

(1)第一次挥手:客户端和服务器建立连接成功后,就会进入ESTAB-LISHED(已建立连接)状态,在发送数据完毕后,客户端会主动发送了连接释放报文,即字段FIN=1的报文,此时的序号为u(u等于上一次发送的数据的最后一个字节加1),之后客户端会进入FIN-WAIT-1(终止等待1)状态。(*TCP规定FIN报文段,即使不携带数据也需要消耗一个序号)

(2)第二次挥手:服务器在接收到客户端的连接释放报文后会给客户端发送确认连接释放的报文(ACK=1,ack=u+1,seq=v)。之后服务器进入CLOSE-WAIT(关闭等待)状态。此刻客户端通往服务器的通道就已经关闭了,但服务器通向客户端的通道还没有关闭。即服务器可以给客户端发送数据,客户端也可以接收到,但此时客户端无法向服务发数据。也就所谓的TCP连接的半关闭状态

(3)第三次挥手:在客户端接收到服务器端的确认报文后客户端会进入FIN-WAIT-2(终止等待2)状态,然后等待服务器发送连接释放报文。如果此时服务器已经没有数据在需要给客户端发送,那么就会给客户端发送连接释放报文(FIN=1,ACK=1,seq=w,ack=u+1),在半关闭状态服务器可能向客户端发送了数据,所以假设seq为w,但确认序号必须为u+1,表示这个报文是确认刚才断开连接的连接释放报文。此时服务器进入LAST-ACK(最终确认)状态,等待客户端确认。

(4)第四次挥手:客户端在接收到服务器发送的连接释放报文后,会给服务器发送确认报文(ACK=1,ack=w+1,seq=u+1),然后进入TIME-WAIT(时间等待)状态。等待2MSL时间后,客户端进入关闭状态。服务器在接收到确认报文后也会进入关闭状态。所以服务的连接会比客户端的连接早一点关闭。

为什么在客户端需要进入TIME-WAIT(时间等待)状态?

(1)为了保证客户端发送的最后一个确认报文能够到达服务器。如果客户端发送的确认报文段丢失,那么服务器在等不到客户端确认的情况在会认为自己发送的FIN+ACK报文客户端没有接收到,所以就会重新发送FIN+ACK报文段(超时重传),那么客户端在收到新的FIN+ACK报文段后,就会重新发送ACK报文段,然后重新启动计时器,继续等待2MSL时间。这样就可以保证客户端和服务器都正常的关闭。如果没有时间等待状态的话,那么一旦客户端发送的确认报文丢失后,服务器就无法正常的进入关闭状态。

(2)防止“已失效连接请求报文段”出现在这个阶段。在经过2MSL时间就可以时间后就可以使得本连接持续时间内的报文段全部消失。

2MSL时间:时间MSL被称为最长报文时间(Maximum Segment Lifetime)。2MSL计时器时从客户端发送确认报文后开始计时的,如果客户端的发送的确认报文丢失,那么在第一个MSL时间后,服务器就会超时重传,最多需要经过MSL时间。所以等待时间就为2MSL。

如果客户端在和服务器连接的过程中,突然由于某些原因(断电、断网)导致客户端无法正常从服务器中退出,那么该如何?

TCP内部设有保活计时器(服务器每次收到客户端的消息后会重置),如果超过两个小时,客户端没有向服务器发送消息,那么服务器就会向客户端发送一个探测报文段,以后每隔75秒就会向客户端发送探测报文段,如果连续10次后客户端没有响应,那么服务器就会关闭这个连接。

 

字节序

字节序的问题是由于CPU对整数再内存中的存放方式造成的。字节多于一个字节的数据类型再内存中的存放位置顺序叫做主机字节序,最常见的字节序有两种:小端字节序和大端字节序。

(1)小端字节序:即Little Endian,简称LE,将数据的最低位凡在内存的起始位置。小端字节序的特点是内存地址较低的位置存放数据的低位字节,内存较高的位置存放数据的高位字节。主要再PC上使用。

(2)大端字节序:即Big Endian,简称BE,将数据高字节放在内存的起始位置。大端字节序的特点内存地址中较低位置存放数据的高位字节,较高的地址存放数据的低位字节。主要在网络上使用,所以大端字节序,又被称为网络字节序。

在网络中的字节序规定位大端字节序,所以在数据从本地向网络传输时,需要将数据转化位大端字节序,在数据从网络上向本地传输时需要将数据转化位小端字节序。

#include <arpa/inet.h>
uint32_t htonl(uint_32 hostlong);
uint16_t htons(uint-16 hostshort);
uint32_t ntohl(uint_32 netlong);
uint16_t ntohs(uint_16 netshort);

h:表示主机(host),n:表示网络(network),l:表示32位整数,s:表示16位短整数。

如果主机时小端字节序,这些函数会将大小端转化然后返回,但如果时大端字节序,那就回直接返回。

//htonl实现
uint_32 htonl(uint_32 value)
{
    return ((value << 24) | ((value << 8)& 0x00FF0000 ) |
     ((value >> 8) | 0x0000FF00) | (value >> 24));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值