本章节介绍socket编程,分享给刚学python的小伙伴,一起学习,共同进步
-
tcp/ip三次握手,4次挥手
三次握手
第一次握手:客户端发送syn包到服务器,进入syn_send状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的syn,同时自己也发送一个ack包,即syn + ack,此时服务器进入到syn_recv状态
第三次握手:客户端接收到服务器的syn + ack包,向服务器发送确认包ack,此包发送完毕,客户端和服务器进入established状态,完成三次握手四次挥手
前两次握手都会相应的产生两次握手,最后一次握手,当服务端收到fin报文时,很可能并不会立即关闭socket,所以只能先回复一个ack报文告诉客户端,你的fin报文我收到了,只有等到我服务端所有的报文都发送完了,我才能发送fin报文,因此不能一起发送。
2.简单案例详解
服务端(先启动)
import socket
server = socket.socket()
# 绑定要监听的端口
server.bind(("localhost",6969))
# 监听
server.listen()
print("我要接收信息了")
conn,addr = server.accept()
print("信息进来了")
data = conn.recv(1024)
print("recv:",data)
conn.send(data.upper())
server.close()
客户端(后启动)
import socket
# 声明socket类型,同时生成socket连接对象
client = socket.socket()
# 连接端口
client.connect(('localhost',6969))
# 发送bytes类型字符串
client.send(b"Are you ok?")
# 接收信息
data = client.recv(1024)
print("recv:",data)
- 复杂案例详解
服务端
import socket,os,time
server = socket.socket()
server.bind(("localhost",9999))
server.listen()
while True:
conn,addr = server.accept()
while True:
recv_data = conn.recv(1024)
if not recv_data:
print("客户端已断开")
break
print("执行指令:",recv_data)
cmd_res = os.popen(recv_data.decode("utf-8")).read()
print("before send:",len(cmd_res.encode()))
if len(cmd_res) == 0:
cmd_res = "server has no output"
# 为啥先要执行cmd_res.encode()?
# cmd_res中文为1个字符,转换为encode1个中文为3个字符
conn.send(str(len(cmd_res.encode())).encode("utf-8"))
# 主要是为了防止粘包
# time.sleep(3)
# 防止粘包,而且不用sleep
client_ack = conn.recv(1024)
print("ack from client")
conn.send(cmd_res.encode("utf-8"))
print("send done")
server.close()
客户端
import socket,os
client = socket.socket()
client.connect(("localhost",9999))
while True:
cmd = input(">>:").strip()
if len(cmd) == 0:
continue
client.send(cmd.encode("utf-8"))
cmd_res_size = client.recv(1024)
# 防止粘包跟server做的配合
client.send("准备好接收了".encode("utf-8"))
recv_size = 0
recv_data = b''
# 一次传输大于1024bytes
while recv_size < int(cmd_res_size.decode("utf-8")):
data = client.recv(1024)
recv_size += len(data)
print(recv_size)
recv_data += data
else:
print("cmd_res receive done...",recv_size)
print(recv_data.decode("utf-8"))
client.close()
TCP/IP网络模型
tcp与udp的区别