在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握手以及如何设计一个单线程多任务版的TCP服务器,这些问题都是本文需要解决的问题。

一、TCP/IP的11种状态

  netstat -na  | grep port_num:可以查看TCP/IP状态

  一个完整的Socket通信过程,会经过11种TCP/IP状态,状态图如下:

  

思考三个问题:

1.为什么TCP/IP通信前需要三次握手?

  因为TCP是全双工协议,得先建立连接才能实现任意一方接收和发送数据的功能,因此需要进行安全认证!这就好比在战争年代,使用电台发送情报一样。

  当A想要与B通信时,A需要发送一个SYN包a给到B,当B收到这个包时,会发送一个ACK a+1的包回给B,同时还要发送一个SYN b给A,确认你是不是要与我通信,然后当A发送ACK b+1给到B时,B收到这个包,那么证明A是对的人,这样A与B之间就能成功建立连接,他们之间就可以相互通信了。

2.为什么TCP/IP断开时需要四次挥手?

  1). 为什么要显式调用两次close()函数?

  当任意一方(假设为A)先调用close()函数时,此时A就不能发送和接收数据了。但是这并不影响另一方(假设为B),也就是说B还可以往TCP/IP缓冲区中写入数据,只不过当内核往A发送数据时会发生错误。当B也调用close()函数时,说明B也要关闭套接字了,就不再发送和接收数据了,他们的通信也就结束了。

  2).FIN_TIME_2状态:

  该状态也称为半连接状态。当A调用close()函数时,此时会在数据流的末尾加上0,当B接收到数据时,read()函数返回0,说明A已经关闭了,那么TCP/IP会偷偷的向A发送一个确认状态,但是B还没有关闭,此时A就处于半连接状态了。

  为什么会出现半连接状态呢?

    因为当B端的read()返回0时,TCP/IP协议知道A已经关闭了,但B还没有调用close()函数,而且TCP/IP协议又是双通道协议,只要B没有关闭,那么B还是可以进行读和写操作的。因此A就不能继续往前推进到TIME_WAIT状态。

  3). TIME_WAIT状态:

  主动关闭的的那一端A最终会推进到TIME_WAIT状态,只有当对方B也关闭了。只不过要等一会(2MSL)再关闭,因为存在网络延迟的原因导致最后一个确认包没能及时发送出去。当处于TIME_WAIT状态时,如果ACY y+1发送失败时,可以重新发送,保证对方真正处于关闭状态。这也是为什么会出现端口可重用选项的原因。

3.在状态图中,我们只看到了10种状态,那还有一种是什么?

  还有一种是CLOSING状态,这种状态比较特殊,只有当双方同时关闭的时候才会出现,状态图变化如下:

    

二、一个简单版的非阻塞服务器

  在经过了上面对TCP/IP协议的详细分析之后,我们可以写一个稍微复杂一些的TCP服务器了,强化一下我们讲过的知识点。

  

 def main():
# 1.创建TCP 服务器
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2.绑定到指定端口
tcp_sock.bind(('', 6060))
# 3.设置为被动模式
tcp_sock.listen(128)
# 4.把服务器端设置为非阻塞模式
tcp_sock.setblocking(False) # 用来保存每个与服务器建立了连接的客户端
clients = list()
# 5.等待客户端的连接
while True:
time.sleep(1)
# 当把阻塞的东西设置为非阻塞时,一定会发成异常
try:
client_sock, addr = tcp_sock.accept()
print(client_sock) # 此时再把客户端设置为非阻塞模式,
client_sock.setblocking(False)
# 把建立好了的连接保存起来
clients.append(client_sock)
except Exception as e:
print('------------没有客户端来连接----------') for new_client in clients:
try:
# 接收数据,因为把客户端设置成了非阻塞,
# 那么所有的阻塞操作都变成了非阻塞模式
data = new_client.recv(1024).decode()
if data: # 此时客户端还在保持连接状态
print(data)
else: # 客户端已经断开连接了
new_client.close()
clients.remove(new_client)
print(data)
except Exception as e:
print('-------客户端未发送数据-------') if __name__ == '__main__':
main()

Python高级网络编程系列之第一篇的更多相关文章

  1. Python高级网络编程系列之第二篇

    在上一篇中,我们深入探讨了TCP/IP协议的11种状态,理解这些状态对我们编写服务器的时候有很大的帮助,但一般写服务器都是使用C/Java语言,因为这些语言对高并发的支持特别好.我们写的这些简单的服务 ...

  2. Python高级网络编程系列之终极篇---自己实现一个Web框架

    通过前面几个小节的学习,现在我们想要把之前学到的知识点给串联起来,实现一个很小型的Web框架.虽然很小,但是用到的知识点都是比较多的.如Socket编程,装饰器传参在实际项目中如何使用.通过这一节的学 ...

  3. Python高级网络编程系列之基础篇

    一.Socket简介 1.不同电脑上的进程如何通信? 进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的! 在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台 ...

  4. Python高级网络编程系列之第三篇

    在高级篇二中,我们讲解了5中常用的IO模型,理解这些常用的IO模型,对于编写服务器程序有很大的帮助,可以提高我们的并发速度!因为在网络中通信主要的部分就是IO操作.在这一篇当中我们会重点讲解在第二篇当 ...

  5. 《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端

    1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...

  6. python 基础网络编程2

    python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...

  7. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  8. 猫哥网络编程系列:详解 BAT 面试题

    从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...

  9. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

随机推荐

  1. VS比较好用的扩展插件总结

    1.Indent Guides 绝对是必须的,有了这些辅助线,代码结构一目了然. 2.CodeMaid 整理与优化代码,并且可以清除空行.必备 把if语句块for语句块折叠 工具->扩展和更新, ...

  2. [日常] go语言圣经-声明,变量,赋值,类型,包和文件习题

    go语言圣经-声明1.四种类型的声明语句:var.const.type和func,分别对应变量.常量.类型和函数实体对象的声明2.包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名 ...

  3. 【JVM】3、JVM问题查找

    1.查看tomcat进程号 两种方式都可以查看tomcat进程号 ps -ef | grep tomcat-web jps -lmvV |grep tomcat-web 结果如下:2556 2.查看进 ...

  4. Jquery/js引入的button的onclik事件只触发一次

    目标描述 我要实现的是:通过监听button的click事件,从而通过ajax向servlet发送请求获取数据库中的数据,然后返回的页面,并要求局部刷新 一次页面的加载是html直接页面初始化本身的 ...

  5. CentOS 6 安装配置JDK+tomcat环境

    1.安装OpenJDK 这里安装的OpenJDK,是开源版本的JDK,我们平时自己电脑上安装的是 Sun JDK(也叫Oracle JDK),OpenJDK可以看作Sun JDK的精简版. 如果想安装 ...

  6. POJ1222(SummerTrainingDay01-E)

    EXTENDED LIGHTS OUT Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11078   Accepted: 7 ...

  7. Bootstrap(一)

    Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目. 使用感觉简约大气便捷,扁平化设计.好多好多CSS.JS....总有你心仪的那一款 ...

  8. 在ASP.NET MVC 中使用ActiveReports报表控件

    随着MVC模式的广泛运用,对Web应用系统的开发带来了巨大的影响,我们好像又回到了原来的ASP时代,视乎这是一种后退而不是一种进步,不过MVC模式给我们带来的影响不仅限于我们所看到的这一点..MVC看 ...

  9. Android--解决EditText放到popupWindow中,原有复制、粘贴、全选、选择功能失效问题

    1.原来是将EditView放到了popupwindow,发现EditView原有的复制.粘贴.全选.选择功能失效了,所以便用DialogFragment代替了popupWindow 直接上代码 ①. ...

  10. [JAVA] 重写以及@Override标签

    以前JAVA看的少,最近做项目,对@Override的调用顺序有点疑惑,故查了一些资料.既然查资料了,那就把能看到的知识点整理一下,以供日后学习. 原文地址请保留http://www.cnblogs. ...