标签:实时 length 否则 字符串 bind type 数值范围 多少 enc
import socket
客户端
1 .创建一个socket对象
sk = socket.socket()
2 .与服务器进行连接
sk.connect(("127.0.0.1",9000))
3.发送数据(二进制的字节流)
sk.send("字符串".encode("utf-8"))
4.关闭连接
sk.close()
服务端
客户端和服务端在收发数据时
一收一发时一对,否则会导致数据异常
send发送 recv接收
1 .创建socket对象
sk = socket.socket()
2 . 绑定对应的ip和端口(注册网络,让其他主机能够找到)
sk.bind(("127.0.0.1",9000))
3 .开启监听
sk.listen()
4 . 建立三次握手
conn,addr = sk.accept()
print(conn,addr)
5 .收发数据(recv里面的参数单位是字节,代表一次最多接收多少数据)
res = conn.recv(1024)
print(res)
print(res.decode("utf-8"))
7 .退还端口
sk.close()
import socket
客户端
1 . 创建udp对象
sk = socket.socket(type=socket.SOCK_DGRAM)
2 . 发送数据
msg ="你好,帅哥"
sk.sendto(msg.encode(),("127.0.0.1",9000))
接收服务端发过来的数据
msg,ser_addr = sk.recvfrom(1024)
print(msg.decode())
print(ser_addr)
服务端
1 .创建udp对象
sk = socket.socket(type=socket.SOCK_DGRAM) (返回udp协议对象)
2 .绑定地址端口
sk.bind(("127.0.0.1",9000))
3 .接收消息(udp作为服务端的时候,第一次一定是接收消息)
msg,cli_addr = sk.recvfrom(1024)
print(msg.decode())
print(cli_addr) # (‘127.0.0.1‘, 56184)
服务端给客户端发消息
msg = "我是老爷们,我不好!"
sk.sendto(msg.encode(), cli_addr )
4 .关闭连接
sk.close()
三.黏包
import struct
pack():把任意长度的字符串转化成具有4个字节的固定长度的字节流
unpack():把4个字节的值恢复成原本的字符串,返回的是元组
import struct
# i => int 要转化的当前数据时整型
"""pack的数值范围不是无限的,上限大概在21个亿左右,不要超过这个值"""
res = struct.pack("i",999999999)
res = struct.pack("i",1234343433)
res = struct.pack("i",2100000011)
print(res)
print(len(res))
# i => 把对应的数据转换成int, 最后返回元祖
tup = struct.unpack("i",res)
print(tup[0]) # (2100000011,)
需要解决黏包的场景:
? 应用场景在实时通讯时,需要阅读此次发的消息是什么
不需要解决黏包的场景:
? 下载或者上传文件的时候,最后要把包都结合在一起,黏包无所谓
1 .针对于tcp协议的黏包现象
客户端
import socket
import time
import struct
sk = socket.socket()
sk.connect(("127.0.0.1",9000))
# 处理收发数据逻辑
# 接受第一次发送过来的数据(数据的大小)
n = sk.recv(4)
tup = struct.unpack("i",n)
n = tup[0]
print(n)
# 第二次发送的真实的数据
res1 = sk.recv(n)
print(res1.decode())
# 第三次发送的真实的数据
res2 =sk.recv(1024)
print(res2.decode())
# 关闭连接
sk.close()
服务端
import socket
import struct
sk = socket.socket()
# 把这句话写在bind之前,让一个端口绑定多个程序,可以重复使用(仅用在测试环节)
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 在网络中注册主机
sk.bind(("127.0.0.1",9000))
# 监听端口
sk.listen()
# 三次握手
conn,addr = sk.accept()
# 处理收发数据逻辑
strvar = input("请输入>>>>:")
msg = strvar.encode()
length = len(msg)
# 第一次把长度先发送过去
res = struct.pack("i",length)
conn.send(res)
# 第二次在发送真实的数据
conn.send(msg)
# 第三次在发送一个数据
conn.send(",world".encode())
# 四次挥手
conn.close()
# 退还端口
sk.close()
标签:实时 length 否则 字符串 bind type 数值范围 多少 enc
原文地址:https://www.cnblogs.com/yunchao-520/p/13062772.html