面试复习—网络知识点-----tcp

一个TCP程序实例

客户端:

①sockfd = socket(AF_INET, SOCK_STREAM, 0);

创建套接字AF_INET表示网际,SOCK_STREAM表示字节流,这两个加在一起就表示TCP套接字

②struct sockaddr_in servaddr;//声明一个网际套接字地址结构

   servaddr.sin_family = AF_INET;

   servaddr.sin_port = htons(13);//绑定服务器端口

   inet_pton(AF_INET, argv[1], &servaddr.sin_addr);//绑定服务器ip地址(先将点分十进制数串转换成32位二进制)

这几步的目的是转件目标地址,表示该套接字应该往哪个服务器上发。

 

(这两歩中间可选调用bind函数,一般不调用时,内核会确定源IP地址,并选择临时端口)

 

connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

应用在sockfd上,使其与servaddr指定的地址建立连接

connect失败时,返回-1,此时必须要关闭当前socket,并重新生成,重新进行connect

④在一个循环中调用

write(sockfd, sendbuff,strlen(sendbuff));//将请求信息写入套接字

read(sockfd, charbuffer, maxLine);//读取套接字中服务器返回的结果

⑤调用exit(0),进程终止的时候会关闭所有的描述符,所以tcp套接字也被关闭

 

服务端:

 

①listenfd = socket(AF_INET, SOCK_STREAM, 0);

创建套接字,AF_INET表示网际,SOCK_STREAM表示字节流,这两个加在一起就表示TCP套接字

②struct sockaddr_in servaddr;//声明一个网际套接字地址结构

   servaddr.sin_family = AF_INET;

   servaddr.sin_port = htons(13);//绑定服务器端口

   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//

这几步指定监听字的端口

bind(listenfd, (SA *)&servaddr, sizeof(servaddr));//将端口与套接字进行绑定;

在客户端中,可以不用调用bind函数,因为内核会为该套接字分配临时端口,如果需要获知该端口号,可以调用getsockname函数获取;但是在服务器中,是必须要指定一个端口的,因为需要众所周知端口给客户端提供服务。

listen(listenfd, LISTENQ);

调用这个函数之后,该套接字就会转换成监听套接字(内核中接收外来连接)

(在调用socket之后产生的套接字为主动套接字,是一个将调用connect发起连接的套接字,使用listen函数之后,该套接字会变成一个被动套接字,指示内核应该接受指向该套接字的外来请求);第二个参数为最大连接个数

socket-----bind-----listen是服务器监听的正常三步骤

 

当有一个客户端请求到来之后(SYN信号到达),会调用三次握手建立连接(自动的过程)。

 

⑤在一个循环体中:

 

connfd = accept(listenfd, (SA *) NULL, NULL);

accept函数其实是等待连接,服务器调用该函数之后会投入到睡眠直到某个客户端连接到达并被内核接受,连接建立之后执行accept返回,返回一个已连接描述符connfd(其实内部创建了已连接套接字);

该函数后面两个参数用来返回已连接对端进程的协议地址,如果不需要,则置NULL。

针对每一个客户端连接请求,都会返回一个已连接描述符

 

read(connfd, reqbuff,MAXLINE);//读取请求信息

write(connfd, buff, strlen(buff));//将反馈信息写入已连接描述符

上面的两步互不干扰,因为TCP是全双工的。

 

close(connfd);//关闭该连接,对于非并发服务器,调用close函数之后会发FIN,执行四次挥手

对于并发服务器(fork产生子进程进行处理),调用close之后,并不一定四次挥手,只是对相应的套接字描述符的计数减一,当减到0的时候才执行挥手。(当然,可以shutdown函数强行发送FIN)

并且,close关闭读和写两个端口,如果只需要关闭一端,就要调用shutdown函数:

int shutdown(int sockfd, int howto);

howto取值:---SHUT_RD:关闭读

    ---SHUT_WR:关闭写

    ---SHUT_RDWR:关闭读和写

 

 

TCP的11个状态转换:

TCP状态转换图

CLOSED: 这个没什么好说的了,表示初始状态。
LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状 态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
ESTABLISHED:这个容易理解了,表示连接已经建立了。
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

对于一个TCP连接:

客户端状态:

CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

服务器状态:

CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

面试题:为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为: 虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到 ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于 LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的 ACK报文。

 

TIME_WAIT状态的套接字过多怎么办?

打开重用和快速回收的两个参数,或者修改TIME_OUT时间。

 

(1)connect请求连接的时候,只有建立连接或者是出错的时候才返回,这样可能会导致长时间阻塞的问题,解决方法:①使用定时器②使用select复用设置非阻塞

(2)keepalive 是什么东西?如何使用?
keepalive,是在TCP中一个可以检测死连接的机制。
.如果主机可达,对方就会响应ACK应答,就认为是存活的。
.如果可达,但应用程序退出,对方就发RST应答,发送TCP撤消连接。
.如果可达,但应用程序崩溃,对方就发FIN消息。
.如果对方主机不响应ack, rst,继续发送直到超时,就撤消连接。默认二个小时。

(3)关于RST信号

RST标示复位、用来异常的关闭连接。一般tcp连接出现错误都会发复位报文段。

----- 发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST。
----- 而接收端收到RST包后,也不必发送ACK包来确认。

 

什么时候发送RST包?
-----建立连接的SYN到达某端口,但是该
端口上没有正在监听的服务

-----异常终止一个连接,使用RST代替FIN释放(此时排队数据可能没有发送完毕,所以是异常释放)

-----检测半打开的连接
-----TCP收到了一个根本不存在的连接上的分节。

-----请求超时。 使用setsockopt的SO_RCVTIMEO选项设置recv的超时时间。接收数据超时时,会发送RST包。

 

(4)socket什么时候可读(也就是执行read的时候不会阻塞)?

------正常情况下,监听套接字接收到对方的connect请求,并且已经完成连接,这个时候这个监听套接字可读

------socket接收缓冲区已接收字节数大于等于socket限制,也就是有数据可以读

------连接的读一半关闭,即对方发FIN,读会直接返回0

------异常情况下,返回-1

socket可读可写的条件

 

(5)TCP的保活定时器

保活:启动服务器和客户端的连接之后,过了很长时间都不会断,甚至中间路由器崩溃重启也不会断。

另一端崩溃
keepalive机制在重复发送探测包到一定次数后报错,由TCP转换为“连接超时”
另一端崩溃而重启
客户端telnet到服务器后,我们拔掉服务器网线重启服务器,服务器重启好后我们在telnet客户端上输入命令。服务器重启后丢失了以前连接的所有信息,此时服务器收到来着telnet客户端的命令,不知道此连接的信息,于是TCP就以复位作为应答来结束TCP连接。
另外一端不可达
拔掉网线,模拟中间路由器崩溃,keepalive探测的时候会引起ICMP差错“不可达--没有到达主机的路由”反馈给主机。

tcp报文头:

Alt text

URG: 标识紧急指针是否有效
ACK: 标识确认序号是否有效
PSH: 用来提示接收端应用程序立刻将数据从tcp缓冲区读走
RST: 要求重新建立连接. 我们把含有RST标识的报文称为复位报文段
SYN: 请求建立连接. 我们把含有SYN标识的报文称为同步报文段
FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报文称为结束报文段

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值