网络编程(二)
socket套接字简介
socket套接字可以帮我们实现C/S架构的程序两端交互
socket套接字可以通过python内置的socket模块快速实现OSI七层操作
"""
以后我们写软件连socket的影子都看不到 因为被封装起来
socket是最底层的原理 很多框架都封装了 其实我们不需要深入研究
"""
socket模块
对于C/S架构的程序,无论编写还是运行,都要遵循:
'优先考虑服务端,有了服务才能有客户'
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
sock, addr = server.accept()
print(addr)
while True:
data = sock.recv(1024)
print(data.decode('utf8'))
msg = input('>').strip()
sock.send(msg.encode('utf8'))
sock.close()
server.close()
import socket
client = socket.socket()
client.connect(('127.0.0.1',8080))
while True:
msg = input('>').strip()
client.send(msg.encode('utf8'))
data = client.recv(1024)
print(data.decode('utf8'))
client.close()
服务端与客户端首次交互
一边是recv那么另一边必须是send 两边不能相同 否则就'冷战'了
通信循环
1.所有通信消息要用户事实输入
利用input获取用户输入信息
2.接收一次消息之后不能结束程序,应当获取输入,返回消息,然后等待下一次接发消息
利用While循环实现
详见上段代码

代码优化及链接循环
1.不能发空消息
搞个if判断len(用户输入即可)
2.反复重启服务端可能会报错>>>:address in use
这个错在苹果电脑报的频繁 windows频率较少
from socket import SOL_SOCKET,SO_REUSEADDR
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
3.链接循环
"""
如果是windows 客户端异常退出之后服务端会直接报错
处理方式
异常处理
如果是mac或linux 服务端会接收到一个空消息
处理方式
len判断
"""
客户端如果异常断开 服务端代码应该重新回到accept等待新的客人
半连接池
listen(5)
设置的最大等待人数 >>>: 节省资源 提高效率
黏包问题
data1 ='aaa'
data2 ='aaa'
data3 ='aaa'
client.send(data1.encode('utf8'))
client.send(data2.encode('utf8'))
client.send(data3.encode('utf8'))
data1 = sock.recv(1024)
print(data1)
data2 = sock.recv(1024)
print(data2)
data3 = sock.recv(1024)
print(data3)
b'aaaaaaaaa'
b''
b''
为什么发了三次数据,结果全都在第一次数据里?
"""
# TCP协议的特点
会将数据量比较小并且时间间隔比较短的数据整合到一起发送
并且还会受制于recv括号内的数字大小(核心问题!!!)
流式协议:跟水流一样不间断
"""
"""
问题产生的原因其实是因为recv括号内我们不知道即将要接收的数据到底多大
如果每次接收的数据我们都能够精确的知道它的大小 那么肯定不会出现黏包
"""
eg:
data1 = sock.recv(3)
print(data1)
data2 = sock.recv(3)
print(data2)
data3 = sock.recv(3)
print(data3)
b'aaa'
b'aaa'
b'aaa'
解决黏包问题
解决思路:
我们可以发送固定大小的数据,客户端接收就不会出现黏包
import struct
data1 = 'Hello world!'
data2 = 'afdkjhfdafklajflkhaslfjahfjkahflksafjl'
print(len(data1), len(data2))
ret1 = struct.pack('i', len(data1))
ret2 = struct.pack('i', len(data2))
print(len(ret1), len(ret2))
res1 = struct.unpack('i',ret1)
res2 = struct.unpack('i',ret2)
print(res1, res2)
1.先将用struct模块打包成固定长度
2.把打包后的长度发过去
3.对方用unpack解析获取真实长度
4.根据真实长度用recv(真实长度)接收数据
代码演示
1.编写一个cs架构的软件
就两个功能
一个视频下载:从服务端下载视频
一个视频上传:从客户端上传视频
"""
只要实现就可以 无需整合(如果能做到更好)
"""
服务端
import socket
import struct
server_packer = socket.socket()
server_packer.bind(('127.0.0.1',8081))
server_packer.listen(1)
sock,addr = server_packer.accept()
with open('1.mp4','rb') as f:
data = f.read()
ret = struct.pack('i', len(data))
sock.send(ret)
sock.send(data)
sock.close()
server_packer.close()
客户端
import struct
import socket
client = socket.socket()
client.connect(('127.0.0.1',8081))
ret = client.recv(4)
res = struct.unpack('i',ret)
data = client.recv(res[0])
with open('2.mp4','wb') as f:
f.write(data)
client.close()

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?