Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下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高级网络编程系列之第一篇的更多相关文章
- Python高级网络编程系列之第二篇
在上一篇中,我们深入探讨了TCP/IP协议的11种状态,理解这些状态对我们编写服务器的时候有很大的帮助,但一般写服务器都是使用C/Java语言,因为这些语言对高并发的支持特别好.我们写的这些简单的服务 ...
- Python高级网络编程系列之终极篇---自己实现一个Web框架
通过前面几个小节的学习,现在我们想要把之前学到的知识点给串联起来,实现一个很小型的Web框架.虽然很小,但是用到的知识点都是比较多的.如Socket编程,装饰器传参在实际项目中如何使用.通过这一节的学 ...
- Python高级网络编程系列之基础篇
一.Socket简介 1.不同电脑上的进程如何通信? 进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的! 在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台 ...
- Python高级网络编程系列之第三篇
在高级篇二中,我们讲解了5中常用的IO模型,理解这些常用的IO模型,对于编写服务器程序有很大的帮助,可以提高我们的并发速度!因为在网络中通信主要的部分就是IO操作.在这一篇当中我们会重点讲解在第二篇当 ...
- 《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端
1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...
- python 基础网络编程2
python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...
- 猫哥网络编程系列:HTTP PEM 万能调试法
注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...
- 猫哥网络编程系列:详解 BAT 面试题
从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...
- 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三
手把手叫你玩转网络编程系列之三 完毕port(Completion Port)具体解释 ...
随机推荐
- ABP的依赖注入
目录 说说ABP的依赖注入 代码追踪 说说ABP的依赖注入 上篇abp运行机制分析分析了ABP在启动时,都做了那些事:这篇我们来说说ABP的最核心的一部分:依赖注入(DependencyInjecti ...
- Beans Game(博弈 | | DP)zoj 3057
Beans Game Time Limit: 5 Seconds Memory Limit: 32768 KB There are three piles of beans. TT and DD pi ...
- LINQ to Objects系列(3)深入理解Lambda表达式
Lambda表达式是学好LINQ很重要的一个知识点,后面的LINQ查询中会大量地使用到Lambda表达式.这篇文章从以下几点进行总结. 1,Lambda表达式的前世今生 2,Lambda表达式的实际运 ...
- Java-函数式编程(二)Lambda表达式
本文首发:Java-函数式编程(二)Lambda表达式 “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lamb ...
- Linux常用基本命令[cp]
cp:复制文件或者目录 用法格式: cp [option] [source] [dest] cp [选项] [源文件] [目标文件] >用root账户,创建文件,复制文件 root@dev:/h ...
- POJ3693(SummerTrainingDay10-J 后缀数组)
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10241 Ac ...
- js实现分享到QQ
js代码 <script src="http://connect.qq.com/widget/loader/loader.js" widget="shareqq&q ...
- SD从零开始29-30
SD从零开始29 外向交货单处理中的特殊功能 批次Batches 你可以在material handled in batches的相关详细屏幕指定一个batch(物料是否使用batches来处理标记在 ...
- 敏捷团队的组织与管理--- MPD软件工作坊培训感想(下)
注:由麦思博(MSUP)主办的2013年亚太软件研发团队管理峰会(以下简称MPD大会)分别于6月15及6月22日在北京.上海举办,葡萄城的部分程序员参加了上海的会议,本文是参会的一些感受和心得. 今年 ...
- Nginx控制客户端请求的速率
使用ngx_http_limit_req_module模块的两个参数 ngx_http_limit_req_module模块用于限制每个IP访问每个定义key的请求速率 1.limit_req_zon ...