python网络编程总结
TCP三次握手的过程
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:
未连接队列
在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于SYN_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
关闭TCP连接
对于一个已经建立的连接,TCP使用改进的三次握手来释放连接(使用一个带有FIN附加标记的报文段)。TCP关闭连接的步骤如下:
第一步,当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。
第二步,主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。
第三步,主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。
第四步,主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。
四次挥手过程
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,
收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。
首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
1.socket简介
TCP是基于链接的,必须先启动服务器,然后再启动客户端去链接服务端
服务端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #可以多次启动
#执行多次的时候会报错,那么怎么办呢、?就在绑卡前面加上上面那句setsockopt方法就ok了
phone.bind(('192.168.20.44',8080))#绑定手机卡(ip,端口)
# 端口号在1024以前的是系统用的,1024以后的都是你自己写的程序去定义的端口
print('starting run......')
phone.listen(5) #开机 5代表的是最多挂起5个,也可以好多个
while True: #链接循环
coon,client_addr=phone.accept()#等待接电话,(coon是建立的链接,客户端的ip和端口号组成的元组)
print(coon,client_addr)
#收发消息
while True: #通信循环
try: #如果不加try...except ,就会报错,因为它不知道你什么时候断开链接的,服务器还以为你在运行
data = coon.recv(1024) #收了1024个字节的消息
print('client data 收到消息:%s'%data.decode('utf-8'))
coon.send(data.upper()) #发消息
except Exception: #因为你不知道客户端什么时候断开链接,
break
coon.close() #挂电话
phone.close() #关机
# 处理逻辑错误的两种方式:
# if 判断
# try...except 异常处理
# 异常处理
# 当你知道直接错误的条件时就用if判断了
# 当程序错误一定发生,但是你又预知不了它出错的条件是什么的时候,就用try...except
服务端