码迷,mamicode.com
首页 > 编程语言 > 详细

python学习第28天

时间:2020-06-07 23:04:56      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:实时   length   否则   字符串   bind   type   数值范围   多少   enc   

一.tcp协议基本语法

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()

二.udp协议基本语法

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()

python学习第28天

标签:实时   length   否则   字符串   bind   type   数值范围   多少   enc   

原文地址:https://www.cnblogs.com/yunchao-520/p/13062772.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!