一 socket

1.什么是socket

看一看图中socket的位置

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

二 基于TCP的套接字

tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

服务器端

#!/usr/bin/env python3#encoding: utf-8#by fixdq

importsocket#ip,端口

ip_prot = ('127.0.0.1', 8884)#缓冲区大小

buffer = 1024

#创建 socket对象

socket_server =socket.socket(socket.AF_INET, socket.SOCK_STREAM)#绑定 ip 端口

socket_server.bind(ip_prot)#服务端开始监听

socket_server.listen(5)whileTrue:#连接对象,客户端地址(ip:port)

conn, address =socket_server.accept()whileTrue:try:#接收信息 ()

msg =conn.recv(buffer)#msg 字母变大写 发送个客户端

conn.send(msg.upper())exceptConnectionError:break

#关闭连接

conn.close()#关闭socket服务

socket_server.close()

客户端

#!/usr/bin/env python3#encoding: utf-8#by fixdq

importsocket#ip,端口

ip_prot = ('127.0.0.1', 8884)#缓冲区大小

buffer = 1024

#获取socket

socket_client =socket.socket(socket.AF_INET, socket.SOCK_STREAM)#根据 ip_port 连接服务器

socket_client.connect(ip_prot)whileTrue:#接受输入

cmd = input("cmd>>:").strip()#发送信息

socket_client.send(cmd.encode('utf-8'))#接受信息

res =socket_client.recv(buffer)#打印信息

print(res.decode('utf-8'))#关闭socket

socket_client.close()

注意点: tcp协议是基于字节流传输数据的的,所以收发信息的格式都是字节(bytes)格式

三 基于UDP的套接字

服务端

#!/usr/bin/env python3#-*- coding: utf-8 -*-#@Author : Fixdq#@File : server.py#@Software: PyCharm

importsocket#ip,端口

ip_port = ('127.122.114.15', 8080)#获取socket

server =socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#绑定IP ,端口

server.bind(ip_port)#循环执行

whileTrue:#接收信息

res, addr = server.recvfrom(1024)#打印信息

print(res.decode('utf-8'))

server.sendto('收到了'.encode('utf-8'), addr)#回收资源

server.close()

客户端

#!/usr/bin/env python3#-*- coding: utf-8 -*-#@Author : Fixdq#@File : client.py#@Software: PyCharm

importsocket#IP port

ip_port = ('127.122.114.15', 8080)#创建客户端

client =socket.socket(socket.AF_INET, socket.SOCK_DGRAM)#循环

whileTrue:#接收用户输入

msg = input('>>>>>>>:').strip()if not msg: continue

#发送信息

client.sendto(msg.encode('utf-8'), ip_port)#接收信息

res,addr = client.recvfrom(1024)#打印信息

print(res.decode('utf-8'),addr)#回收资源

client.close()

四 粘包现象以及处理

1.什么是粘包现象

须知:只有TCP有粘包现象,UDP永远不会粘包

两种情况下会发生粘包:

----发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)

----接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

2.怎么处理粘包

问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据

解决方案:

自定义报头,为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据

需要用到  struct模块该模块可以把一个类型,如数字,转成固定长度的bytes

具体用法,参照官方Doc

3.具体示例

importjson,struct#假设通过客户端上传1T:1073741824000的文件a.txt

#为避免粘包,必须自定制报头

header={'file_size':1073741824000,

'file_name':'/a/b/c/d/e/a.txt',

'md5':'8f6fbf8347faa4924a76856701edb0f3'} #1T数据,文件路径和md5值

#为了该报头能传送,需要序列化并且转为bytes

head_bytes=bytes(json.dumps(header),encoding='utf-8') #序列化并转成bytes,用于传输

#为了让客户端知道报头的长度,用struck将报头长度这个数字转成固定长度:4个字节

head_len_bytes=struct.pack('i',len(head_bytes)) #这4个字节里只包含了一个数字,该数字是报头的长度

#客户端开始发送

conn.send(head_len_bytes) #先发报头的长度,4个bytes

conn.send(head_bytes) #再发报头的字节格式

conn.sendall(文件内容) #然后发真实内容的字节格式

#服务端开始接收

head_len_bytes=s.recv(4) #先收报头4个bytes,得到报头长度的字节格式

x=struct.unpack('i',head_len_bytes)[0] #提取报头的长度

head_bytes=s.recv(x) #按照报头长度x,收取报头的bytes格式

header=json.loads(json.dumps(header)) #提取报头

#最后根据报头的内容提取真实的数据,比如

real_data_len=s.recv(header['file_size'])

s.recv(real_data_len)

#!/usr/bin/env python3#-*- coding: utf-8 -*-#@Author : Fixdq#@File : tcp_server.py#@Software: PyCharm

importjsonfrom socket import *

importsubprocessimportstruct

ip_port= ('127.155.101.25', 8090)

server=socket(AF_INET, SOCK_STREAM)

server.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)

server.bind(ip_port)

server.listen(5)whileTrue:

conn, addr=server.accept()whileTrue:

cmd= conn.recv(1024)if not cmd: break

print('--------->cmd----', cmd.decode('utf-8'))

res= subprocess.Popen(cmd.decode('utf-8'),

shell=True,

stdout=subprocess.PIPE,

stderr=subprocess.PIPE)

ret=res.stdout.read()ifret:

back=retelse:

back=res.stderr.read()#把真实数据的相关信息,包装成字典

head ={'len': len(back)

}#json 序列化 字典信息

head_str =json.dumps(head)#只包含报头长度 (报头的报头)

#i 模式,产生一个固定4字节长度bytes

head_head = struct.pack('i', len(head_str))#发送 (报头的报头)

conn.send(head_head)#报头数据

conn.send(head_str.encode('utf-8'))#真实数据

conn.send(back)

conn.close()

server.close()

服务端(自定义报头)

#!/usr/bin/env python3#-*- coding: utf-8 -*-#@Author : Fixdq#@File : tcp_client.py#@Software: PyCharm

importjsonfrom socket import *

importstruct

ip_port= ('127.155.101.25', 8090)

client=socket(AF_INET, SOCK_STREAM)

client.connect_ex(ip_port)whileTrue:

cmd= input('>>>>>:').strip()

client.send(cmd.encode('utf-8'))#接收 报头的报头 (固定长度 4 字节)

head_head = client.recv(4)#反解出 报头的长度

head_len = int(struct.unpack('i',head_head)[0])#接收 自定义报头

head =client.recv(head_len)#拿到 自定义报头的长度

body_len = json.loads(head.decode('utf-8'))['len']#接收 真实的数据

data =client.recv(body_len)print(data.decode('utf-8'))

client.close()

客户端(自定义报头)

自定义报头总结:

我们可以把报头做成字典,字典里包含将要发送的真实数据的详细信息,然后json序列化,然后用struck将序列化后的数据长度打包成4个字节(4个自己足够用了)

发送时:

先发报头长度

再编码报头内容然后发送

最后发真实内容

接收时:

先手报头长度,用struct取出来

根据取出的长度收取报头内容,然后解码,反序列化

从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容

python全栈开发网络_Python 全栈开发:网络编程相关推荐

  1. python必须连网开发吗_Python以太坊开发节点和网络选择

    为什么我需要连接到一个节点? 以太坊协议定义了一种方法,用于人们通过网络与智能合约相互作用.为了获得关于合约.账户余额和新交易状态等最新的信息,协议需要与网络上的节点进行连接.这些节点不断地共享最新的 ...

  2. python把字符串3des加密_Python干货之六大密码学编程库

    信息加密和信息隐藏是实现信息安全与保密的主要手段.除了一些经典的加密解密算法和自己设计的加密算法之外,我们还可以充分利用Python标准库和扩展库提供的丰富功能来辅助我们完成信息加密解密实现.本文收集 ...

  3. python全栈开发网络_Python全栈开发:django网络框架(二)

    Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...

  4. python全栈开发优势_Python全栈开发多少钱?学Python价格贵吗?

    Python全栈开发培训多少钱?学习Python是大家进入编程世界的理想之选,而且Python也是一门非常受欢迎的编程,可以从事的领域有很多. 从目前市场上的行情来说,一般情况下Python培训的费用 ...

  5. python全栈开发下载_python全栈开发神器 - 『精品软件区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...

    将安卓手机打造成你的python全栈开发利器 超神利器- 相信多数安卓用户都使用过Qpython这款移动端的Python编辑器吧?之前我也研究过一阵子这个工具,但因为一次简单的爬虫让我对它失望之极.Q ...

  6. python全栈开发中级_python全栈开发中级班全程笔记(第二模块)第一部分:文件处理...

    第二模块 第一部分:文件处理与函数 #插曲之人丑就要多读书:读书能够提高个人素质与内涵,提升个人修养与能力,以及层次的提升. 推荐书籍:追风筝的人.白鹿原 电影:阿甘正传.辛德勒的名单 第一节:三元运 ...

  7. python实现四位一并法_python 全栈开发,Day4(列表切片,增删改查,常用操作方法,元组,range,join)...

    一.列表 列表是python中的基础数据类型之一,它是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如: li = ['alex',123,Ture,(1,2,3,'wusir') ...

  8. python全栈开发内容_Python全栈开发之Day02

    一. 回顾上节主要内容 1. python是一门解释型弱类型高级语言 2. python的解释器 CPython, PyPy, JPython, IronPython, Ipython 3. prin ...

  9. python全栈开发总结_python全栈开发 * 12 知识点汇总 * 180530

    ⼀. 通⽤装饰器的回顾 1.开闭原则: 对增加功能开放. 对修改代码封闭 2.装饰器的作⽤: 在不改变原有代码的基础上给⼀个函数增加功能 3.通⽤装饰器的写法: def wrapper(fn): de ...

最新文章

  1. 吴恩达Coursera机器学习 - Chapter 4 多变量线性回归
  2. [转]parseUrl函数
  3. java的默认值规则_Java 8:默认方法解析规则
  4. python中if控制语句_Python中流程控制语句之IF语句
  5. 【带着canvas去流浪(12)】用Three.js制作简易的MARVEL片头动画(上) #华为云·寻找黑马程序员#
  6. harbor安装_Harbor任意管理员注册漏洞(CVE-2019-1609) (附:批量利用poc)
  7. 《图解Http》8: 用户身份认证Cookie管理session; 9:HTTP的追加协议(websoket, webDAV)...
  8. gc:C语言的垃圾回收库-中文
  9. 基于JAVA+SpringMVC+Mybatis+MYSQL的汽车饰品销售系统
  10. Linux基础命令--grep/find
  11. 微信聊天记录云存储服务如何收费
  12. dwg转换pdf怎么转换?
  13. 推荐几部不错的网络玄幻小说
  14. 2019年9月中国编程语言排行榜
  15. html中<img src=““ alt=““>标签里面alt的作用
  16. 阿里云智能技术战略架构师陈绪:透视2019云计算酣战
  17. 正则匹配0-999区间数字
  18. 补天漏洞平台:让更多的白帽子脱离黑产
  19. chrome浏览器f12的network里的请求行变得很大的解决方案
  20. 【2017 BSUIR Semifinal D】Friends rescue 题解

热门文章

  1. 当一名程序员喝醉之后......
  2. 线程的故事:3 位“母亲”成就了优秀的我!
  3. 支付宝 “集五福”今日开启;小米起诉美国国防部;Chrome 再次屏蔽七个端口 | 极客头条...
  4. 教育行业 A 股 IPO 第一股,如何做成程序员培训这门生意 | 极客头条
  5. 2020年入门数据分析选择Python还是SQL?七个常用操作对比!
  6. Smalltalk 语言的地位为何一落千丈?
  7. BTC 重现“自由落体”式暴跌,原来是受这几个因素影响?
  8. 女朋友:你能给我讲讲单例模式吗?
  9. 一文学会 SSH 服务!
  10. 这本Python书被封年度神作!程序员:比女友强太多!