python 找不到socket_python应用之socket编程

tcp/udp下的socket的基本使用

基于tcp的socket

Tcp是基于链接的,必须先启动服务端,然后启动客户端进行链接

服务端:

ss = socket() #创建服务器套接字

ss.bind() #把地址绑定到套接字

ss.listen() #监听链接

inf_loop: #服务器无限循环

cs = ss.accept() #接受客户端链接

comm_loop: #通讯循环

cs.recv()/cs.send() #对话(接收与发送)

cs.close() #关闭客户端套接字

ss.close() #关闭服务器套接字(可选)

客户端:

cs = socket() #创建客户套接字

cs.connect() #尝试连接服务器

comm_loop: #通讯循环

cs.send()/cs.recv() #对话(发送/接收)

cs.close() #关闭客户套接字

简单的实现:

这里是单个的 一次通信

python 找不到socket_python应用之socket编程_第1张图片

python 找不到socket_python应用之socket编程_第2张图片

ContractedBlock.gif

ExpandedBlockStart.gif

mport socket #AF_INET 基于网络通信, SOCK_STREAM(基于流的,tcp)

phone= socket.socket(socket.AF_INET, socket.SOCK_STREAM) #买手机

phone.bind(('127.0.0.1', 8000)) #绑定手机卡

phone.listen(5) #开机(监听) # 5表示 最多有5个可以发送连接, 放在链接池中

print('--->')

conn, addr= phone.accept() #(等电话,等待连接,会阻塞)(触发的是3次握手)

#收发消息(在tcp协议中触发的是数据传输)#注意收发信息不是用手机, 而是conn这条连接

mesg = conn.recv(1024) #收消息

print('客户端发来的消息是:',mesg)

conn.send(mesg.upper())#发消息

#断开链接 (在tcp协议中触发的是4次挥手)

conn.close()#关机

phone.close()

服务端

ContractedBlock.gif

ExpandedBlockStart.gif

importsocket

phone= socket.socket(socket.AF_INET, socket.SOCK_STREAM) #买手机

phone.connect(('127.0.0.1', 8000)) #拨通电话 (触发的是三次握手)

#收发数据#phone.send('hello'.encode('utf-8')) # socket不支持字符串发送,仅支持字节编码发送所以要用

phone.send(bytes('hello', encoding='utf-8')) #这两个发送一样,只要转换成二进制就行

data = phone.recv(1024)print('收到服务端发来的消息', data)

客户端

这个是简单的交互模式

ContractedBlock.gif

ExpandedBlockStart.gif

#!/usr/bin/env python#-*- coding: utf-8 -*-#@Time : 18-5-14 下午5:56#@Author : LK#@File : fu_ceshi.py#@Software: PyCharm

from socket import *buffersize= 1024

#tcp_server = socket(AF_INET, SOCK_STREAM) #流式套接字

tcp_server.bind(('127.0.0.1', 8000))

tcp_server.listen(5)#为了接收多个连接

whileTrue:#等待连接

conn, add = tcp_server.accept() #等待连接 ,会阻塞

print('双向连接是:',conn)print('客户端地址是',add)#收发信息

whileTrue:#try:

#这个异常实在win中,但是在linux下有时候是死循环, 因为客户端突然断掉,conn就没了,mesg一直是空

mesg =conn.recv(buffersize)if notmesg:print('客户端你断开连接了')break

print('服务端接收的信息:',mesg.decode('utf-8'))

conn.send(mesg.upper())print('服务端以发送回去')#except Exception:

#break

conn.close()#关闭连接

tcp_server.close()

服务端

ContractedBlock.gif

ExpandedBlockStart.gif

from socket import *buffersize=1024tcp_client=socket(AF_INET, SOCK_STREAM)#主动连接

tcp_client.connect(('127.0.0.1', 8000))#收发信息

whileTrue:

send_mesg= input('请输入要个服务端发送的信息,break停止').strip('')#如果发送的是空格,重新发送

if not send_mesg: continue

if send_mesg == 'break':print('客户端停止发送信息了')break

else:

tcp_client.send(send_mesg.encode('utf-8'))print('客户端已发送消息')

mesg=tcp_client.recv(buffersize)print('客户端接受的信息:',mesg.decode('utf-8'))#关闭连接

tcp_client.close()

客户端

基于udp的socket

udp是无链接的,先启动哪一端都不会报错

服务端:

ss= socket() #创建一个服务器的套接字

ss.bind() #绑定服务器套接字

inf_loop: #服务器无限循环

cs = ss.recvfrom()/ss.sendto() #对话(接收与发送)

ss.close() #关闭服务器套接字

客户端

cs= socket() #创建客户套接字

comm_loop: #通讯循环

cs.sendto()/cs.recvfrom() #对话(发送/接收)

cs.close() #关闭客户套接字

udp基本实现:

ContractedBlock.gif

ExpandedBlockStart.gif

#!/usr/bin/env python#-*- coding: utf-8 -*-#@Time : 18-5-15 下午1:38#@Author : LK#@File : udp_服务端.py#@Software: PyCharm

from socket import *ip_port= (('127.0.0.1', 8080))

buffsize= 1024udp_server= socket(AF_INET, SOCK_DGRAM) #数据报套接字

udp_server.bind(ip_port)whileTrue:

data, addr=udp_server.recvfrom(buffsize)print('客户端发来的消息',data.decode('utf-8'))

udp_server.sendto(data.upper(), addr)#注意这里是addr

udp_server.close()

udp服务端

ContractedBlock.gif

ExpandedBlockStart.gif

#!/usr/bin/env python#-*- coding: utf-8 -*-#@Time : 18-5-15 下午1:38#@Author : LK#@File : udp_客户端.py#@Software: PyCharm

from socket import *ip_port= (('127.0.0.1', 8080))

buffsize= 1024udp_client= socket(AF_INET, SOCK_DGRAM) #数据包套接字

whileTrue:try:

mesg= input('>>>').strip()

udp_client.sendto(mesg.encode('utf-8'), ip_port)#recvfrom 接受的是一个元祖, 里面是信息和对方地址

data, addr =udp_client.recvfrom(buffsize)print('服务端发来的是', data.decode('utf-8'))#print(data)

exceptKeyboardInterrupt as e:print(e)print('程序异常中断')break

#recv 在自己这端的缓冲区为空时,会阻塞(返回的是信息)#recvfrom 不会阻塞 (返回是一个元祖,分别是接受的信息和地址)

#tcp没有实现并发,而udp默认实现了,因为udp不用建立连接,直接网端口发送,而tcp需要建立连接

udp客户端

udp的客户端可以开多个,

常用函数

服务端套接字函数

s.bind() 绑定(主机,端口号)到套接字

s.listen() 开始TCP监听

s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数

s.connect() 主动初始化TCP服务器连接

s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数

s.recv() 接收TCP数据

s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)

s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)

s.recvfrom() 接收UDP数据

s.sendto() 发送UDP数据

s.getpeername() 连接到当前套接字的远端的地址

s.getsockname() 当前套接字的地址

s.getsockopt() 返回指定套接字的参数

s.setsockopt() 设置指定套接字的参数

s.close() 关闭套接字

面向锁的套接字方法

s.setblocking() 设置套接字的阻塞与非阻塞模式

s.settimeout() 设置阻塞套接字操作的超时时间

s.gettimeout() 得到阻塞套接字操作的超时时间

面向文件的套接字的函数

s.fileno() 套接字的文件描述符

s.makefile() 创建一个与该套接字相关的文件

tcp粘包问题

首先要知道socket的收发消息的原理

python 找不到socket_python应用之socket编程_第3张图片

send 是发送给用 对方后,存在对方的内核态中,

recv 收消息是从自己的缓存中收

只有tcp有粘包现象,udp没有,但是udp会发生丢包问题, 就是发的数据太多,到那时udp的缓冲区,只能接收固定大小,剩下的就丢了, 所以udp没有tcp可靠

流程就是, 服务端发送数据给自己的缓冲区,然后通过网络发送给客户端的缓冲区,

客户端从自己的缓冲区进行取数据,recv函数 一次可能取不完,就可能会出现粘包问题

如果recv取的少的话,或者发送的过多,就可能会出现粘包问题

Recv 是从自己的 内核态中去数据, 如果数据过多的话就会出现粘包问题

解决粘包问题思路: 可以先获取消息的大小, 然后死循环一直发,知道发送到指定大小在停止, 收包也是如此

所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

粘包的表现

ContractedBlock.gif

ExpandedBlockStart.gif

#!/usr/bin/env python#-*- coding: utf-8 -*-#@Time : 18-5-16 上午8:42#@Author : LK#@File : tcp_粘包问题_服务端.py#@Software: PyCharm

#粘包问题发生的原因:#第一种情况:tcp在发送的时候,基于流的方式发送数据,发送端要等缓冲区满后才发送出去,造成粘包#(发送数据的时间很短,数据很小,就会和在一起发送)

#第二种情况,发送端发送的数据很大,但是接收端的缓冲区已经放不下,直接从缓冲区里面拿#多次都从缓冲区里面取数据(就是发送的大,但是取的少)

#解决方法:一般是先发送一个数据大小,然后回复一下,在用循环发送数据,高级办法(struct),跟高级(偏函数)

from socket import *tcp_socket=socket(AF_INET, SOCK_STREAM)

ip_port= (('127.0.0.1', 8080))

tcp_socket.bind(ip_port)

tcp_socket.listen(5)

conn, addr=tcp_socket.accept()print('连接的信息',conn)print('详细信息',addr)#收发数据

whileTrue:#'''第二种粘包现象,就是发的多,每次收的少'''

#mesg = conn.recv(2)

#print('第一次接受的',mesg.decode('utf-8'))

#mesg = conn.recv(1)

#print('第二次接受的',mesg.decode('utf-8'))

#mesg = conn.recv(1)

#print('第三次接受的',mesg.decode('utf-8'))

'''第一种粘包现象, 发的少收得多'''mesg= conn.recv(1024)print('第一次接受的',mesg.decode('utf-8'))

mesg= conn.recv(1)print('第二次接受的',mesg.decode('utf-8'))

mesg= conn.recv(1)print('第三次接受的',mesg.decode('utf-8'))

coon.close()

tcp_socket.close()

粘包的表现_服务端

ContractedBlock.gif

ExpandedBlockStart.gif

#!/usr/bin/env python#-*- coding: utf-8 -*-#@Time : 18-5-16 上午8:41#@Author : LK#@File : tcp_粘包问题_客户端.py#@Software: PyCharm

from socket import *tcp_client=socket(AF_INET, SOCK_STREAM)

ip_port= (('127.0.0.1',8080))

tcp_client.connect(ip_port)#收发消息

whileTrue:'''第一中粘包现象,发的少,收的多'''tcp_client.send('第一次发送的'.encode('utf-8'))

tcp_client.send('第二次发送的'.encode('utf-8'))

tcp_client.send('第三次发送的'.encode('utf-8'))

tcp_client.recv(4)#'''第二种粘包现象,发的多收的少'''

#tcp_client.send(b'hhhh')

#tcp_client.send(b'ff')

#tcp_client.recv(4)

粘包的表现_客户端

图解模式:

粘包的本质:接收端不知道,从缓存中取多少

第一种粘包现象:

接收端

python 找不到socket_python应用之socket编程_第4张图片

发送端

python 找不到socket_python应用之socket编程_第5张图片

运行结果

1396803-20180518174659804-1593706486.png

第二种粘包现象

接收端

python 找不到socket_python应用之socket编程_第6张图片

发送端

python 找不到socket_python应用之socket编程_第7张图片

结果

1396803-20180518174728279-1771862563.png

tcp模拟终端,shell执行结果来显示 粘包问题并解决

如果是linux下 ,不用修改, 输入ls 显示当前目录下的文件,然后输入ifconfig 查看ip等信息,返回的信息比较多,一次不能提取完,再输入其他命令就会产生错误

windows 中 如果产生编码错误就把utf-8 改成gbk

命令用win下的 如 dir 然后 ipconfig 再输入 其他的

ContractedBlock.gif

ExpandedBlockStart.gif

#存在粘包问题

importsubprocessfrom socket import *

from tcp_模拟终端处理数据 importdealwith

ip_port= (('127.0.0.1', 9000))

buffsize= 1024tcp_server=socket(AF_INET, SOCK_STREAM)try:

tcp_server.bind(ip_port)

tcp_server.listen(5)print('还没有人连接')#等待多个连接

whileTrue:try:

conn, addr=tcp_server.accept()print('客户端连接信息', conn)print('客户端地址', addr)#收发消息

whileTrue:

mesg=conn.recv(buffsize)if notmesg:print('客户端中断连接了,服务器等待下次连接')break

print('客户端发送的是', mesg.decode('utf-8'))

data=dealwith(mesg)#将这些封装成了一个函数

'''# # 处理从客户端接收的信息

# # res是接收的信息,经过shell脚本处理后的结果

# res = subprocess.Popen(mesg.decode('utf-8'), shell=True,

# stdin=subprocess.PIPE,

# stdout=subprocess.PIPE,

# stderr=subprocess.PIPE

# )

# # 获取错误信息

# err = res.stderr.read().decode('utf-8')

# if not err:

# data = res.stdout.read().decode('utf-8')

# else:

# data = err'''conn.sendall(data)print('服务端已发送')exceptKeyboardInterrupt as e:print('外部强制结束')breakconn.close()exceptOSError as e:print('端口以用过')

tcp_server.close()

模拟终端_产生粘包_服务端

ContractedBlock.gif

ExpandedBlockStart.gif

#存在粘包问题

from socket import *tcp_client=socket(AF_INET, SOCK_STREAM)

ip_port= (('127.0.0.1', 9000))

buffsize= 1024tcp_client.connect(ip_port)whileTrue:#mesg = input('>>>').strip()

#去除左右空格

mesg = input('>>>').lstrip().rstrip()if not mesg: continuetcp_client.send(mesg.encode('utf8'))print('客户端已发送')

data=tcp_client.recv(buffsize)if notdata:print('服务端发来的是空信息')continue

print('服务端发来的信息是:',data.decode('utf-8'))

tcp_client.close()

模拟终端_产生粘包_客户端

ContractedBlock.gif

ExpandedBlockStart.gif

#!/usr/bin/env python#-*- coding: utf-8 -*-#@Time : 18-5-15 下午5:23#@Author : LK#@File : tcp_模拟终端处理数据.py#@Software: PyCharm

importsubprocessdefdealwith(mesg):#处理从客户端接收的信息

#res是接收的信息,经过shell脚本处理后的结果

res = subprocess.Popen(mesg.decode('utf-8'), shell=True,

stdin=subprocess.PIPE,

stdout=subprocess.PIPE,

stderr=subprocess.PIPE

)#获取错误信息

err =res.stderr.read()if noterr:

data=res.stdout.read()if notdata:#data = '你输入的数据返回值为空'.encode('utf-8')

return '你输入的数据返回值为空'.encode('utf-8')else:

data=errreturndata#这里返回的是一个字节的形式

#res = subprocess.Popen('ls', shell=True,#stdin=subprocess.PIPE,#stdout=subprocess.PIPE,#stderr=subprocess.PIPE#)## stdin=subprocess.PIPE, 标准输入, 输入的内容会放在管道中## stdout=subprocess.PIPE, 标准输出,就是结果会放在pipe这个管道中## stderr=subprocess.PIPE, 标准错误,如果结果错误 会放在这个管道中#

## 读取管道内容## print(res.stdout.read()), 读取之后,管道里面的就没有输出了

数据处理

第一种处理粘包的方法:

思路: 在发送端首先发送给接受端一个4个字节大小的数据,内容是要发的真是数据的大小.接收端在取数据的时候取4个字节,

然后给发送端发送一个准备接受的信号,当发送端接收到这个信号时,开始发送信息.接收端开始循环接收信息.

struct的用法

ContractedBlock.gif

ExpandedBlockStart.gif

importsubprocessfrom socket import *

from tcp_模拟终端处理数据 importdealwith

ip_port= (('127.0.0.1', 9000))

buffsize= 1024tcp_server=socket(AF_INET, SOCK_STREAM)try:

tcp_server.setsockopt(SOL_SOCKET, SO_REUSEPORT,1)

tcp_server.bind(ip_port)

tcp_server.listen(5)print('还没有人连接')#等待多个连接

whileTrue:try:

conn, addr=tcp_server.accept()print('客户端连接信息', conn)print('客户端地址', addr)#收发消息

whileTrue:

mesg=conn.recv(buffsize)if notmesg:print('客户端中断连接了,服务器等待下次连接')break

print('客户端发送的是', mesg.decode('utf-8'))

data=dealwith(mesg)#解决粘包:,发送端先发送一个消息的大小,接收端回复一个准备接收的信号,然后发送端开始循环发送信息

length =len(data)

conn.send(str(length).encode('utf-8'))

read_send= conn.recv(buffsize).decode('utf-8')#注意这里的问题,就是发送一个大的文件,用sendall,,如何发送,还是在于如何取

if read_send == 'read_recv':

conn.sendall(data)print('服务端已发送')exceptKeyboardInterrupt as e:print('外部强制结束')breakconn.close()exceptOSError as e:print('端口以用过')#tcp_server.close()

tcp_server.close()

解决粘包问题_low版_服务端

ContractedBlock.gif

ExpandedBlockStart.gif

#low版解决粘包问题

from socket import *

importsys

tcp_client=socket(AF_INET, SOCK_STREAM)

ip_port= (('127.0.0.1', 9000))

buffsize= 1024tcp_client.connect(ip_port)#3 用connect_ex()比较好, 可以重复利用 端口

whileTrue:#去除左右空格

mesg = input('>>>').lstrip().rstrip()if not mesg: continuetcp_client.send(mesg.encode('utf8'))print('客户端已发送')

data_lenth= int(tcp_client.recv(1024).decode('utf-8'))#解决粘包问题

tcp_client.send('read_recv'.encode('utf-8'))

recv_leng=0

data= b''

while recv_leng buffsize:

data+=tcp_client.recv(buffsize)

recv_leng=len(data)else:#当剩余的数据 小于缓冲区大小时

data += tcp_client.recv(data_lenth -recv_leng)

recv_leng=len(data)if notdata:print('服务端发来的是空信息')continue

print('服务端发来的信息是:', data.decode('utf-8'))

tcp_client.close()

解决粘包问题_low版_客户端

第二种处理粘包方法:推荐使用

思路struct,发送端用struct.pack() (一般用int类型占4个字节) 将要发送的数据的大小打包后发送过去,然后在发送真实数据.两个必然会粘包.

但是接收端在接收的时候先接收4个字节,然后用struct.unpack()解包,得到数据大小,再利用循环接受真实数据.

struct用法:

http://www.cnblogs.com/coser/archive/2011/12/17/2291160.html

ContractedBlock.gif

ExpandedBlockStart.gif

#用struct 解决粘包

importstructimportsubprocessfrom socket import *

from tcp_模拟终端处理数据 importdealwith

ip_port= (('127.0.0.1', 9000))

buffsize= 1024tcp_server=socket(AF_INET, SOCK_STREAM)#这一句是 重复利用 端口

try:

tcp_server.setsockopt(SOL_SOCKET, SO_REUSEPORT,1)

tcp_server.bind(ip_port)

tcp_server.listen(5)print('还没有人连接')#等待多个连接

whileTrue:try:

conn, addr=tcp_server.accept()print('客户端连接信息', conn)print('客户端地址', addr)#收发消息

whileTrue:

mesg=conn.recv(buffsize)if notmesg:print('客户端中断连接了,服务器等待下次连接')break

print('客户端发送的是', mesg.decode('utf-8'))

data=dealwith(mesg)#解决粘包:,发送端先发送一个消息的大小,接收端回复一个准备接收的信号,然后发送端开始循环发送信息

length =len(data)

conn.send(struct.pack('i', length))

conn.sendall(data)print('服务端已发送')exceptKeyboardInterrupt as e:print('外部强制结束')breakconn.close()exceptOSError as e:print('端口以用过')#tcp_server.close()

tcp_server.close()

解决粘包-服务端_推荐使用

ContractedBlock.gif

ExpandedBlockStart.gif

#struct解决粘包

from socket import *

importstruct

tcp_client=socket(AF_INET, SOCK_STREAM)

ip_port= (('127.0.0.1', 9000))

buffsize= 1024tcp_client.connect(ip_port)whileTrue:#mesg = input('>>>').strip()

#去除左右空格

mesg = input('>>>').lstrip().rstrip()if not mesg: continuetcp_client.send(mesg.encode('utf8'))print('客户端已发送')#解决粘包

#服务端会发送过来一个 数据的大小,和 一个真实数据的包,两个必定会粘包,但是解包是分开来解,先解4个字节(对方发来的数据包大小)

data_length = tcp_client.recv(4)

length= struct.unpack('i', data_length)[0]#循环接收数据

recv_leng =0

data= b''

while recv_leng buffsize:

data+=tcp_client.recv(buffsize)

recv_leng=len(data)else:

data+= tcp_client.recv(length-recv_leng)

recv_leng=len(data)if notdata:print('服务端发来的是空信息')continue

print('服务端发来的信息是:', data.decode('utf-8'))

tcp_client.close()

解决粘包-客户端

udp 的丢包问题

# udp传输数据是以数据报的方式发送,每次发送都是发送完整的数据,但是接收方接收的可能小于发送放,就会产生丢包

# 因为每次都是发送一个完整的,取时也是取完缓冲区,所以不会发生粘包,但是会发生丢包,意味着,这是不安全的

ContractedBlock.gif

ExpandedBlockStart.gif

from socket import *udp_server=socket(AF_INET, SOCK_DGRAM)

ip_port= (('127.0.0.1',8080))

udp_server.bind(ip_port)#收发消息

whileTrue:#这里的6 出现两个汉字是因为, 汉字的编码方式不同(3个字节,在win中不同)

data, addr = udp_server.recvfrom(6)print('第一次接收的信息是:',data.decode('utf-8'))

data, addr= udp_server.recvfrom(6)print('第二次接收的信息是',data.decode('utf-8'))#udp_server.sendto(data,addr)

服务端

ContractedBlock.gif

ExpandedBlockStart.gif

from socket import *udp_client=socket(AF_INET, SOCK_DGRAM)

ip_port= (('127.0.0.1', 8080))

buffsize= 1024

whileTrue:

data= '第一次发送的信息'udp_client.sendto(data.encode('utf-8'), ip_port)

data= '第二次发送的信息'udp_client.sendto(data.encode('utf-8'), ip_port)

udp_client.recvfrom(10)

客户端

socket_server实现并发

基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环

socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)

#这样就tcp服务器就能被多个用户链接了, 客户端流程不变

classMyServer(socketserver.BaseRequestHandler):defhandle(self):#self.request # 相当于 conn

#self.client_address # 相当于 addr

whileTrue:'''在这里写收发消息'''s= socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer) #将上面的类实例化一个

s.serve_forever() #一直开启状态

tcp_socket_server并发版_服务端

importsocketserverimportstructfrom 封装处理粘包_拆包 importUnPacket, SendDataclassMyServer(socketserver.BaseRequestHandler):defhandle(self):

self.requestprint('连接人的信息')print('conn是', self.request) #conn

print('addr是', self.client_address) #addr

whileTrue:'''收发消息'''head_data= self.request.recv(4)if not head_data: breakreal_data=UnPacket(head_data, self.request)print('客户端发来的是:%s客户端地址是是%s' % (real_data.decode('utf-8'), self.client_address))#回复客户端,防止粘包

send_data = 'aaaaaaaa'SendData(send_data, self.request)if __name__ == '__main__':#pass

print('还没有人连接')

s= socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer) #多线程

#s = socketserver.ForkingTCPServer(('127.0.0.1', 8080), MyServer) # 多进程win中不行

#服务器一直开着

s.serve_forever()

客户端

from socket import *

from 封装处理粘包_拆包 importUnPacket, SendDataimportstruct

tcp_server=socket(AF_INET, SOCK_STREAM)

ip_port= ('127.0.0.1', 8080)

buffsize= 1024tcp_server.connect_ex(ip_port)whileTrue:'''收发信息'''mesg= input('>>>').strip()#防止粘包处理函数

SendData(mesg, tcp_server)

mesg= tcp_server.recv(4)if not mesg: breakrecv_data=UnPacket(mesg, tcp_server)print('服务端发送的信息是',recv_data.decode('utf-8'))

tcp_server.close()

处理粘包的问题,封装了一下后是:

封装处理粘包_拆包

importstruct#传过来包的头部信息,和连接,返回接受的数据是一个byte类型

defUnPacket(head_data ,conn):

buffsize= 4

'''解决粘包,需要传送过数据头,和连接'''real_data_length= struct.unpack('i',head_data)[0]

real_data= b''recv_length=0#这个少了点优化

#while recv_length < real_data_length:

#real_data += conn.recv(1024)

#recv_length = len(real_data)

while recv_length buffsize:

real_data+=conn.recv(buffsize)

recv_length=len(real_data)else:

real_data+= conn.recv(real_data_length-recv_length)

recv_length=len(real_data)returnreal_data#接受要发送的数据,是字符串,和要发送的链接(客户端发送tcp_server, 服务端发送conn或self.request))

defSendData(real_data,conn):'''发送包,发两次,'''head_length= struct.pack('i', len(real_data)) #后面是一个整数,所以是四个字节, 这里有个优化

conn.send(head_length)

conn.sendall(real_data.encode('utf-8'))print('客户端发送成功')

你可能感兴趣的:(python,找不到socket)