Python 高级网络操作 - Python Advanced Network Operations
Python 高级网络操作 - Python Advanced Network Operations
Half Open Socket,
一个单向的 socket 被称为 half open socket, 即数据只能在一个方向上传输.
Half Open Socket 是通过在 socket 对象上调用 shutdown() 方法得到.
shutdown 接收一个 numeric 类型的参数,
0 - 表示调用之后禁止读
1 - 表示调用之后禁止写
2 - 表示调用之后禁止读和写
一旦关闭了某一个方向(读/写), socket 就不能再在该方向上被重新打开了.
shutdown()是累计的, 也就是调用 shutdown(0) 再调用 shutdown(1) 跟
直接调用一个 shutdown(2) 效果是一样的. Half Open Socket 通常被应用在一下儿 3 种情形中,
1, 想要确保所有写好的数据都已经被传送出去.
调用 shutdown()的时候, 只有在缓存里面的数据都被成功发出去后方法才会有返回.
2, 用来 debug, 捕获潜在的异常/错误.
Half Open Socket 是捕获试图写一个不可写的 socket, 或者读一个不可读
的 socket 的异常的好方法.
3, 在程序是用了 fork() 或 多线程的时候, 用来防止其他进程/线程的某些操作. socket 超时 - socket timeout
settimeout(seconds)
对一个 socket 对象调用 settimeout(secs) 方法后, 如果经过在 sces 秒之内什么都
没有发生(读/写), 则会产生一个 socket.timeout 异常, 链接机会断开,
例子,
... ...
sock, addr = S.accept()
sock.settimeout(9)
... ... 结束标识,
通过 socket 传输不确定长度的字符串的会遇到一个问题 - 不知道什么时候数据发送结束.
通常,有两种方法可以解决这个问题,
1, 通过指定字符串结束标识符(尾)
这个标识符通常是一个 NULL 字符(python - '\0') 或 newline 字符(python - '\n')
需要注意的问题是需要保证设定的结束符在所传输的内容中的'唯一'性.
2, 通过指定字符串长度指示符(首)
先发发送一个数字用来表示数据的长度, 接受方会根据这个数字长度的数据.
在网络上发送整形数据的时候,通常有一下儿两种选择,
a, 发送 ASCII 码(接收方收到后需要解码)
b, 直接发送 二进制 数, 一般位长是 16 或 32 位.
为了解决不同平台的二进制数据的编码方法不同的问题, 一种标准的二进制数据
表示法 - 网络字节顺序( Network Byte Order )被采纳. 在发送一个二进制数之前,
该二进制数被转换成 Network Byte Order; 接收方收到后, 在使用该数据之前做
'反向转换'. 广播数据,
广播数据不能用 TCP 实现, 他多数是用 UDP 来实现的.
当接受方收到一个广播信息后, 系统内核会检查目的地的端口号信息. 如果系统上有一个在 listen 监听该端口
号的进程,则信息会被发送给该进程, 否者信息会被忽略掉.
例子,
发送方,
import socket
S = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
S.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 广播 broadcast
S.sendto("Hi there!",('<broadcast>', 12345)) # host = '<broadcast>' while 1:
try:
data, addr = S.recvfrom(1024)
print("%s is connecting" % clientsocket.getpeername())
except (KeyboardInterrupt,SystemExit) as e:
print(e)
raise
if not len(data):
break
print("Received message : %s from : %s",(data, addr)) 接受方,
import socket S = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
S.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 链接关闭后,端口立即可用
S.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 广播 broadcast
S.bind(('', 12345)) while 1:
try:
mes, addr = S.recvfrom(8192)
print("Got message : %s from : %s" % (mes, addr))
S.sendto("ACK", addr) # 回复不是广播
except (KeyboardInterrupt, SystemExit) as e:
print(e)
raise 通过 poll() 或 select() 实现事件通知,
通常, socket 上的 I/O 是阻塞的, 当一个操作(读/写)未结束,程序会阻塞.
在 nonblocking 模式中, 如果在没有完全准备好的 socket 对象调用 send() 或 recv() 方法
会触发 socket.error 异常. 在这种情况下, 就需要在调用 recv() 之前检查一下儿, socket 上
是不是有可以接受的 data. select() 和 poll() 就是满足检查需求的两个标准工具. 他们可以使
系统在某个 socket 上有事件发生的时候通知程序发生了什么, 从而在程序中进行有针对性的操作.
select() 接口是早起被普遍使用的, 但是在需要同时观察多个 socket 的事件的时候, 会变得很慢.
Windows 系统不支持 poll(), 必须使用 select(). 例子,
poll()
import socket, select
try:
S = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error as e:
print("Error at creating socket : %s" % e) try:
s.connect(("www.zzyzz.top", 80))
except socket.gaierror as e:
print("Address related error : %s" % e)
except socket.error as e:
print("Connection error : %s" % e)
P = select.poll()
P.register(S.fileno(), select.POLLIN | select.POLLERR | select.POLLHUP)
# POLLIN 普通或优先级带数据可读
# POLLERR 发生错误
# POLLHUP 对方描述符挂起
# POLLRDNORM 普通数据可读
# POLLRDBAND 优先级带数据可读
# POLLPRI 高优先级数据可读
# POLLOUT 普通数据可写
# POLLWRNORM 普通数据可写
# POLLWRBAND 优先级带数据可写
# POLLNVAL 描述字不是一个打开的文件 while 1:
res = P.poll(100) # poll 间隔 100 毫秒
if len(res):
if res[0][1] == select.POLLIN:
data = S.recv(1024)
if not len(data):
print("Connection closed")
break
print("Received data : %s" % data)
else:
print("Errors occurred")
break select() 来解决 I/O 阻塞
select(rlist, wlist, elist[, timeout])
rlist - '读' 的文件对象列表
wlist - '写' 的文件对象列表
elist - '错误' 的文件对象列表
timeout - 可选参数, 接收浮点类型, 指明超时的时间(秒) select() 方法的调用返回 3 个tuple, 每一个 tuple 都是一个对象列表, 顺序对应参数顺序. import socket, select
try:
S = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error as e:
print("Error at creating socket : %s" % e) try:
s.connect(("www.zzyzz.top", 80))
except socket.gaierror as e:
print("Address related error : %s" % e)
except socket.error as e:
print("Connection error : %s" % e) while 1:
infds, outfds, errfds = select.select([S],[],[S],0.05)
if len(infds):
data = S.recv(1024)
if not len(data):
print("Connection closed")
break
print("Received data : %s" % data)
if len(errfds):
print("Errors occurred")
break
Python 高级网络操作 - Python Advanced Network Operations的更多相关文章
- python高级之操作数据库
python高级之操作数据库 本节内容 pymysql介绍及安装 使用pymysql执行sql 获取新建数据自增ID fetch数据类型设置 1.pymysql介绍及安装 在python2中连接数据库 ...
- 第九篇:python高级之操作数据库
python高级之操作数据库 python高级之操作数据库 本节内容 pymysql介绍及安装 使用pymysql执行sql 获取新建数据自增ID fetch数据类型设置 1.pymysql介绍及 ...
- Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...
- Python高级进阶(一)Python框架之Django入门
传说中的Django Django由来 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的框架模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下 ...
- Python高级网络编程系列之第三篇
在高级篇二中,我们讲解了5中常用的IO模型,理解这些常用的IO模型,对于编写服务器程序有很大的帮助,可以提高我们的并发速度!因为在网络中通信主要的部分就是IO操作.在这一篇当中我们会重点讲解在第二篇当 ...
- Python高级网络编程系列之第二篇
在上一篇中,我们深入探讨了TCP/IP协议的11种状态,理解这些状态对我们编写服务器的时候有很大的帮助,但一般写服务器都是使用C/Java语言,因为这些语言对高并发的支持特别好.我们写的这些简单的服务 ...
- Python高级网络编程系列之基础篇
一.Socket简介 1.不同电脑上的进程如何通信? 进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的! 在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台 ...
- Python高级网络编程系列之终极篇---自己实现一个Web框架
通过前面几个小节的学习,现在我们想要把之前学到的知识点给串联起来,实现一个很小型的Web框架.虽然很小,但是用到的知识点都是比较多的.如Socket编程,装饰器传参在实际项目中如何使用.通过这一节的学 ...
- Python高级特性:Python迭代、生成器、列表生成式
迭代 给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历称为迭代(Iteration). 在java和C语言中,迭代是通过循环list的下标来完成的,Pyth ...
随机推荐
- 1z0-062 题库解析2
Examine the parameters for a database instance: NAME TYPE VALUE-------------------------------- ---- ...
- 序言vue.js介绍
vue.js :渐进式JavaScript框架 vue.js 优点 1.体积小 例如:压缩后 33k; 2.更高的运行效率 基于虚拟dom,一种可以预先通过JavaScript进行各种计算,把最终的D ...
- C++Primer第五版 6.1节练习
练习6.1:实参和形参的区别是什么? 通俗解释: 实参是形参的初始值.编译器能以任意可行的顺序对实参求值.实参的类型必须与对应的形参类型匹配. 详解1) 形参变量只有在函数被调用时才会分配内存,调用结 ...
- Babel+vscode实现APICloud开发中兼容ES6及以上代码
本文出自APICloud官方论坛, 感谢论坛版主 penghuoyan 的分享. 使用APICloud开发时,考虑到兼容问题一直使用ES5开发,时间越久感觉越落后,整理了一个兼容ES6的开发环境, ...
- cogs 1588. [USACO Feb04]距离咨询 倍增LCA
1588. [USACO Feb04]距离咨询 ★★ 输入文件:dquery.in 输出文件:dquery.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] 农夫 ...
- 最大区间和变形 - codeforces
题意 : 可以选择操作一串区间,将区间内的某一个数全部变成一个新的数字,询问整个区间中某个数字的出现次数总共有多少个? 思路分析 : 首先最后选的一定是一个区间,然后 ans = cnt(1, l-1 ...
- Redis 分布式锁的正确实现方式( Java 版 )
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- xpath写法大全(适用于selenium、robotframework)
1.//input[contains(@id, 'txttags')] 定位出来是个ID,但是ID后面的“102”是个随机数,所以用定位ID的方法就不行了,用firepath生成的xpath也会包括这 ...
- C语言入门:一维数组的概要
数组的概念: 具有相同数据的有序集合 一维数组的定义格式: int a[5]; 类型说明符 数组名(标识符)[常量表达式(长度)]; 一维数组下标 : 数组的下标 从0开始 最大下标值 为 数组的 ...
- Bootstrap自带的那些常用插件
1.Bootstrap自带的那些常用插件. 1.1模态框 模态框的HTML代码放置的位置 务必将模态框的HTML代码放在文档的最高层级内(也就是说,尽量作为 body 标签的直接子元素),以避免其他组 ...