首页 > 编程语言 >30.Python基础篇-socket模块

30.Python基础篇-socket模块

时间:2024-12-21 17:42:14浏览次数:5  
标签:socket Python 30 TCP server sk client message

介绍

socket 模块是用于实现网络通信的模块。它提供了底层网络操作的接口,使得用户可以通过网络实现客户端和服务器之间的数据传输。通过 socket 模块,程序可以通过网络进行数据传输、连接和通信。

使用socket模块创建一个TCP服务

server端代码

# server端代码

import socket

sk = socket.socket()  # 创建一个TCP协议的套接字
sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  #
sk.bind(('127.0.0.1', 8080))  # 作为服务端需要绑定一个IP和端口

# 监听传入的连接请求。
sk.listen()  # 只有TCP协议需要监听,UDP不需要

# accept() 方法接收客户端的连接。
conn, addr = sk.accept()  # 只有TCP协议需要

# 接收客户端发送的数据,并解码
ret = conn.recv(1024).decode("UTF-8")  # 1024指接收1024个字节的数据

# 向客户端发送数据,发送的数据必须是bytes类型
conn.send(bytes('hello client', encoding='UTF-8'))

# 最后关闭连接和socket服务
conn.close()
sk.close()

 

client端代码

# client端代码

import socket

sk = socket.socket()

# 相比server端,client端不需要绑定IP和端口,但是需要向指定IP和端口与服务端进行连接
sk.connect(('127.0.0.1', 8080))  # 与server端连接
# 至此。不需要做其他操作,可以直接发送或接收数据

# 向服务端发送数据,与server同样的,只能发送bytes类型
sk.send(bytes('hello server', encoding="UTF-8"))

# 接收服务端数据,并解码
ret = sk.recv(1024).decode("UTF-8")

# 关闭socket。
sk.close()

 

使用socket模块创建一个UDP服务

server端代码

# UDP 协议  server端

import socket

# 创建一个UDP协议的套接字
sk = socket.socket(type=socket.SOCK_DGRAM)  # type=socket.SOCK_DGRAM表示创建一个UDP的套接字

# 作为服务端需要绑定IP和端口
sk.bind(('127.0.0.1', 8080))

# UDP协议直接接收数据即可,不用监听等其他操作。但是UDP协议的server端,一上来必须是接受数据,不能是发送数据。
# recvfrom返回一个元组。第一个元素是客户端发送的内容,第二个元素是客户端的地址
msg, addr = sk.recvfrom(1024)
print(msg)  # b'hello server'
print(addr)  # ('127.0.0.1', 64098)

# 使用sendto方法,向客户端发送数据。第一个参数为bytes类型的内容,第二个参数为客户端的地址
sk.sendto(bytes('hello client', encoding='UTF-8'), addr)

# 最后关闭server
sk.close()

 

client端代码

# UDP 协议  client端

import socket

# 创建一个UDP协议的套接字
sk = socket.socket(type=socket.SOCK_DGRAM)  # type=socket.SOCK_DGRAM表示创建一个UDP的套接字
ip_port = ('127.0.0.1', 8080)  # 普通的变量

# 使用sendto方法,向服务端发送数据。第一个参数为bytes类型的内容,第二个参数为目标服务端的地址
# 作为UDP协议客户端,一上来必须是发送数据的一方,不能是接收数据的一方
sk.sendto(b'hello server', ip_port)

# 使用recvfrom接受数据,1024表示接收数据的最大字节数
# recvfrom返回一个元组。第一个元素是服务端发送的内容,第二个元素是服务端的地址
server_msg, addr = sk.recvfrom(1024)
print(server_msg)  # b'hello client'
print(addr)  # ('127.0.0.1', 8080)

# 最后关闭server
sk.close()

 

TCP协议的黏包问题

黏包和拆包的原因

  1. 发送方黏包
    • 如果发送方发送的消息非常小,TCP 在传输过程中可能会将多个消息合并在一起,发送为一个大的数据包。这是因为 TCP 会尽量减少包头的开销,以提高效率。
  2. 接收方拆包
    • 接收方可能会在一个接收操作中收到多个包,或者在多个接收操作中收到一个包。这是因为 TCP 并不关心数据包的边界,它只关心数据流的顺序和完整性

如何处理黏包问题?

1.固定长度消息

2.分隔符协议

3.长度前缀协议

解决黏包问题

使用struct模块解决黏包问题

使用 struct 模块来解决 TCP 通信中的黏包问题,通常是通过在发送数据时为每个消息添加一个固定长度的“消息长度字段”,然后接收端根据该长度字段来正确地解析消息。这种方法通常称为“长度前缀协议”,是解决黏包和拆包问题的常见做法。

原理

  1. 发送方:在发送数据前,先将数据的长度(通常是 4 字节)放在消息的前面。这样,接收方就可以先读取长度字段,确定消息的完整长度,再去读取数据。
  2. 接收方:接收时,首先读取长度字段(确定消息的长度),然后根据这个长度读取完整的消息。

 代码演示

server端代码

import socket
import struct

# 创建TCP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8080))
server_socket.listen(1)

# 等待客户端连接
print("Server listening...")
client_socket, client_address = server_socket.accept()
print(f"Connected by {client_address}")

# 接收消息的长度字段(4 字节)
length_data = client_socket.recv(4)

if length_data:
    # 使用struct解包出消息长度
    message_length = struct.unpack('!I', length_data)[0]
    print(f"Expected message length: {message_length}")

    # 根据长度字段接收实际的消息数据
    message_data = client_socket.recv(message_length)
    print(f"Received message: {message_data.decode('utf-8')}")

# 关闭连接
client_socket.close()
server_socket.close()

 

client端代码

# client端
import socket
import struct

# 创建TCP套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8080))

# 要发送的消息
message = "Hello, this is a test message."

# 计算消息的长度
message_length = len(message)

# 使用struct将消息的长度和消息内容一起打包
# '!I' 表示网络字节顺序(大端)和一个无符号整数(长度字段)
# 'message.encode('utf-8')' 将消息内容转换为字节
packed_message = struct.pack('!I', message_length) + message.encode('utf-8')

# 发送打包好的数据
client_socket.sendall(packed_message)

# 关闭连接
client_socket.close()

 

标签:socket,Python,30,TCP,server,sk,client,message
From: https://www.cnblogs.com/mingbo-1/p/18620992

相关文章

  • 【华为OD-E卷-寻找关键钥匙 100分(python、java、c++、js、c)】
    【华为OD-E卷-寻找关键钥匙100分(python、java、c++、js、c)】题目小强正在参加《密室逃生》游戏,当前关卡要求找到符合给定密码K(升序的不重复小写字母组成)的箱子,并给出箱子编号,箱子编号为1~N。每个箱子中都有一个字符串s,字符串由大写字母、小写字母、数字、标点符号......
  • 【华为OD-E卷-最多提取子串数目 100分(python、java、c++、js、c)】
    【华为OD-E卷-最多提取子串数目100分(python、java、c++、js、c)】题目给定[a-z],26个英文字母小写字符串组成的字符串A和B,其中A可能存在重复字母,B不会存在重复字母,现从字符串A中按规则挑选一些字母,可以组成字符串B。挑选规则如下:同一个位置的字母只能挑选一次......
  • 数据结构与算法Python版 散列与区块链
    文章目录一、散列二、完美散列函数三、完美散列函数的应用-区块链一、散列散列Hashing构造一个新的数据结构,使得查找算法的复杂度降到O(1),这种概念称为“散列Hashing”由数据项的值来确定其存放位置,数据项应该出现在大概什么位置,就可以直接到那个位置看看数据项是......
  • 数据结构与算法Python版 顺序查找与二分查找
    文章目录一、顺序查找二、二分查找一、顺序查找顺序查找SequentialSearch通过下标,我们就可以按照顺序来访问和查找数据项,这种技术称为“顺序查找”如果数据项保存在如列表这样的集合中,我们会称这些数据项具有线性或者顺序关系在Python列表中,这些数据项的存储位置......
  • 29.Python基础篇-网络基础理论
    重要知识点BS与CS架构BS(Browser/Server)架构:基于浏览器和服务器的架构,客户端通过浏览器访问服务器上的应用程序或服务。特点:客户端只需要一个浏览器,无需安装复杂的软件,服务器端处理大部分业务逻辑。应用:Web应用(如Web浏览器访问网站)。CS(Client/Server)架构:客户端和服务......
  • 基于 Django和Python 的影视数据可视化系统
    文章目录程序资料获取一、项目技术二、项目内容和项目介绍三、核心代码四、效果图五、资料获取程序资料获取......
  • python语言jjsp爬虫程序代码
    importrequestsimportreimportosy=‘https://vip.lz-cdn5.com/20220705/30947_eb6de902/1200k/hls/mixed.m3u8’h={‘user-agent’:‘Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/131.0.0.0Safari/537.36Edg/131.0.......
  • 学期:2024-2025-1 学号:20241303 《计算机基础与程序设计》第十三周学习总结
    作业信息这个作业属于哪个课程<班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如2024-2025-1计算机基础与程序设计第十三周作业)这个作业的目标<写上具体方面>加入云班课,参考本周学习资源;自学教材《C语言程序设计》第12章并完......
  • C语言-jum-python-简单四则运算
    本题要求编写程序,计算2个整数的和、差、积、商并输出。题目保证输入和输出全部在整型范围内。输入格式:输入2个正整数A和B。每行输入一个数据。输出格式:在4行中按照格式“A运算符B=结果”顺序输出和、差、积、商。输入样例:83输出样例:8+3=118-3= 58*3=......
  • 使用Anaconda和PyTorch编写深度学习Python代码
    摘要:通过Anaconda的虚拟环境和PyTorch的深度学习框架来建立Python的深度学习代码一、安装Anaconda在官网下载Anaconda,DownloadAnacondaDistribution|Anaconda等待漫长的下载过程这时候我推荐来一把酣畅淋漓的原神:二、配置Anaconda的国内镜像源参考:conda安装包_......