文档章节

Python 学习笔记 - socket(粘包及其处理方式)

乐搏学院
 乐搏学院
发布于 2017/04/06 15:45
字数 925
阅读 99
收藏 0

前面学习了基本的最原始的单线程的socket的原理,下面学习一个新的知识点-粘包。由于我们接受的命令是recv(1024),那么如果当另一端发送的数据大于1024个字节的时候,他就会出现粘包的问题。每次只能发送1024个字节,如果我们直接放在一个循环里面不断发送,不断接受,那么当数据发完以后,他就会卡住在那里,因为我们知道在正常连接状态里,socket的accept和recv都是会进入阻塞的状态(换句话说,没有客户连接或者客户发空包,那么就会卡住!)。如何处理这个问题呢?一个思路是发送之前,先打个招呼,告诉对方自己要发送的字节长度,这样对方可以根据长度判断什么时候终止接受。

 

下面看一个模拟SSH操作的实例,客户端发送命令,服务器端执行之后返回结果给客户端

 

Server.py

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

#!/usr/bin/env python

# -*- coding:utf-8 -*-

 

import socket

import subprocess #导入执行命令模块

ip_port=('127.0.0.1',9999#定义元祖

#买手机

s=socket.socket()  #绑定协议,生成套接字

s.bind(ip_port)    #绑定ip+协议+端口:用来唯一标识一个进程,ip_port必须是元组格式

s.listen(5)        #定义最大可以挂起胡链接数

 

while True:  #用来重复接收新的链接

    conn,addr=s.accept()   #接收客户端胡链接请求,返回conn(相当于一个特定胡链接),addr是客户端ip+port

    #收消息

    while True#用来基于一个链接重复收发消息

            try#捕捉客户端异常关闭(ctrl+c)

                recv_data=conn.recv(1024#收消息,阻塞

                if len(recv_data) == 0:break #客户端如果退出,服务端将收到空消息,退出

                #发消息

                p=subprocess.Popen(str(recv_data,encoding='utf8'),shell=True,stdout=subprocess.PIPE) #执行系统命令,windows平

                                                                                                      # 台命令的标准输出是gbk编码,需要转换

                res=p.stdout.read()   #获取标准输出

                print(res,type(res))

                if len(res) == 0:   #执行错误命令,标准输出为空,

                    send_data='cmd err'

                else:

                    send_data=str(res,encoding='gbk')  #命令执行ok,字节gbk---->str---->字节utf-8

                send_data=bytes(send_data,encoding='utf8')

                #解决粘包问题

                ready_tag='Ready|%s' %len(send_data)

                conn.send(bytes(ready_tag,encoding='utf8')) #发送数据长度

                feedback=conn.recv(1024)  #接收确认信息

                feedback=str(feedback,encoding='utf8')

                if feedback.startswith('Start'):

                    conn.send(send_data)  #发送命令的执行结果

            except Exception:

                break

  

    conn.close()

 

client.py

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#!/usr/bin/env python

# -*- coding:utf-8 -*-

 

import socket

ip_port=('127.0.0.1',9999)

s=socket.socket()

s.connect(ip_port)  #链接服务端,如果服务已经存在一个好的连接,那么挂起

while True:        #基于connect建立的连接来循环发送消息

    send_data=input(">>: ").strip()

    if send_data == 'exit':break

    if len(send_data) == 0:continue

    s.send(bytes(send_data,encoding='utf8'))

    #解决粘包问题

    ready_tag=s.recv(1024#收取带数据长度的字节:Ready|9998

    ready_tag=str(ready_tag,encoding='utf8')

    if ready_tag.startswith('Ready'):#Ready|9998

        msg_size=int(ready_tag.split('|')[-1])  #获取待接收数据长度

    start_tag='Start'

    s.send(bytes(start_tag,encoding='utf8')) #发送确认信息

    #基于已经收到的待接收数据长度,循环接收数据

    recv_size=0

    recv_msg=b''

    while recv_size < msg_size:

        recv_data=s.recv(1024)

        recv_msg+=recv_data

        recv_size+=len(recv_data)

        print('MSG SIZE %s RECE SIZE %s' %(msg_size,recv_size))

    print(str(recv_msg,encoding='utf8'))

     

s.close()

 

 

登录乐搏学院官网http://www.learnbo.com/

或关注我们的官方微博微信,还有更多惊喜哦~

 

 

本文出自 “麻婆豆腐” 博客,请务必保留此出处http://beanxyz.blog.51cto.com/5570417/1860016

0

© 著作权归作者所有

共有 人打赏支持
乐搏学院
粉丝 9
博文 526
码字总数 707467
作品 0
丰台
程序员
私信 提问
python之socket编程

一、客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构   互联网中处处是C/S架构   如购物网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种)   腾讯作为服务端为你...

菜鸟小于
2018/08/18
0
0
python标准库00 学习准备

Python标准库----走马观花 python有一套很有用的标准库。标准库会随着python解释器一起安装在你的电脑上的.它是python的一个组成部分.这些标准库是python为你准备的利器,可以让编程事半功倍....

肖邦0526
2015/12/29
0
0
Socket/WebSocket应用及IM粘包 分包等

> Socket/WebSocket应用 WebSocket的frame?google的protobuf在IM中的使用? IM、金融、股价、视频会议等这样一些应用来说,所需要的不过是高实时、低延时。比较好的可选方案呢?比较流行的是...

shareus
2018/04/28
0
0
python的网络编程

一、系统和网络 1、系统 操作系统: (Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的...

技术小阿哥
2017/11/27
0
0
python基础---网络编程(socket编程)

socket编程 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组...

迟到的栋子
2018/07/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

js数组遍历和对象遍历

数组遍历 for for(var i=0,len=arr.length;i<len;i++){console.log(arr[i]);} forEach - ES5语法,性能比for弱,不能使用break终止循环,不能使用return arr.forEach(function(item,inde......

祖达
19分钟前
0
0
Java网络编程

基本概念 网络IO会涉及到同步,异步,阻塞,非阻塞等几个概念。 一个网络IO读取过程是数据从 网卡 到 内核缓冲区 到 用户内存 的过程。同步和异步区别在于数据从内核到用户内存的过程是否需要...

春哥大魔王的博客
41分钟前
2
0
Spring "reg:zookeeper" 的前缀 "reg" 未绑定等类似问题解决方案。

今天同事遇到一个Spring启动加载配置文件时,不识别reg:zookeeper标签的问题。 我查看配置,发现是Spring配置文件的头部没有引入reg标签的命名空间,具体如下图: 所以,以后遇到类似的标签未...

花漾年华
今天
2
0
阿里云领衔云市场

近期,2018年Q4及全年的全球云基础设施服务市场数据新鲜出炉,发布方是美国市场研究机构Synergy Research Group。这个机构是专做电信网络市场情报的公司,成立于1999年,每年都会公布各大公有...

linuxCool
今天
2
0
C++友元函数和友元类(C++ friend)详解

私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书...

shzwork
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部