网络编程(二)
一.socket(套接字)
1.基于TCP协议的socket通信
sever端
1 import socket 2 sk = socket.socket() 3 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 4 sk.listen() #监听链接 5 conn,addr = sk.accept() #接受客户端链接 6 ret = conn.recv(1024) #接收客户端信息 7 print(ret) #打印客户端信息 8 conn.send(b'hi') #向客户端发送信息 9 conn.close() #关闭客户端套接字 10 sk.close() #关闭服务器套接字(可选)
client端
import socket sk = socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字
2.标准通信循环
server端
import socket server = socket.socket() # 生成一个对象 server.bind(('127.0.0.1',8080)) # 绑定ip和port server.listen() # 半连接池 while True: conn, addr = server.accept() print(addr) # ('127.0.0.1', 51323) 客户端的地址 while True: try: data = conn.recv(1024) print(data) if len(data) == 0:break conn.send(data.upper()) except ConnectionResetError as e: print(e) break conn.close()
client端
import socket client = socket.socket() client.connect(('127.0.0.1',8080)) while True: msg = input('>>>:').encode('utf-8') if len(msg) == 0:continue client.send(msg) data = client.recv(1024) print(data)
3.粘包问题
server端
import socket import subprocess sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn,addr = sk.accept() while True: try: cmd = conn.recv(1024).decode('utf-8') if len(cmd) == 0:break res = subprocess.Popen(cmd,shell= True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) stdout = res.stdout.read() stderr = res.stderr.read() conn.send(stdout) conn.send(stderr) except ConnectionResetError: break
client端
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: cmd = input('请输入cmd:').strip() if len(cmd) == 0 :continue sk.send(cmd.encode('utf-8')) res = sk.recv(1024) print(res.decode('gbk'))
粘包造成的原因:
粘包现象只发生在tcp协议中:
1.从表面看,粘包问题主要是因为发送方和接收方的缓存机制,tcp协议面向流通信的特点
2.实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的
4.解决粘包
server端
import socket import subprocess import json import struct sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn,addr = sk.accept() while True: try: cmd = conn.recv(1024).decode('utf-8') if len(cmd) == 0:break res = subprocess.Popen(cmd,shell= True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) stdout = res.stdout.read() stderr = res.stderr.read() ret = stdout+stderr head = {'name':'zzp','size':len(ret)} json_head = json.dumps(head) head_pack = struct.pack('i',len(json_head)) sk.send(head_pack) sk.send(json_head.encode('utf-8')) sk.send(ret) except ConnectionResetError: break
client端
import socket import struct import json sk = socket.socket() sk.connect(('127.0.0.1',8080)) while True: cmd = input('请输入cmd:').strip() if len(cmd) == 0 :continue sk.send(cmd.encode('utf-8')) head_pack = sk.recv(4) head_len = struct.unpack('i',head_pack)[0] head_json = sk.recv(head_len).decode('utf-8') head = json.loads(head_json) size = head['size'] recv_size = 0 real_data = b'' while recv_size < size: data = sk.recv(1024) real_data += data recv_size += len(data) print(real_data.decode('gbk'))
万般皆下品,唯有读书高!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)