• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于python:用-Python-写网络编程二

python 搞代码 3年前 (2022-02-20) 24次浏览 已收录 0个评论

回溯前文

第一篇只是开篇了数据结构和一些传输的例子。第二篇会讲网络编程传输协定在 Python 场景下如何应用。
依据上文的回复,程序上会先讲 Tcp,上面进入正题。

复习功课:用 Python 写网络编程(一)

深度优化过的传输协定-Tcp

Tcp 规范来自上个世纪 80 年代,也是历经了 30 多年的改良和优化。然而这些优化不是应用层的,防止简明扼要,有趣味能够本人去理解下。
这外面一些观点前面也会用 Python 去验证。
那么学习网络协议,在第一篇外面是协定用的数据结构。下一步就是学习 Tcp 和惯例的 http 镞有什么不同,先从构造上进行梳理,构造别离有:

传输状态(蕴含传输的各种设置)
链接地址

传输状态

Http 在应用层分为多个域,整体比较复杂,比 TCP 更简单,只是 Http 应用场景比 Tcp 广域,所以游刃有余和更多了解。
Http 镞和 Tcp 底层都是 socket,这个 http 在 web 那层做了大量限度和革新,所以有了更多域。
Http 镞不打算这里介绍,进入正题。Tcp 也是数据流,能够取得字节数组 bytes 长度的。
传输状态这层是由 socket 做的,Python 那层做了大量的容纳,不必设置很简单的 socket 设置。

socket 原生函数须要通过 nodename、servname、ai_flags、ai_family、ai_socktype、ai_protocol 来设置
ai_family:AF_INET Ipv4,目前大部分都是 Ipv4。 AF_INET6,就是 Ipv6。
ai_socktype:SOCK_STREAM 是数据流,也就是 TCP 的流设置。SOCK_DGRAM 是数据包,UDP 的包设置。

def tcp_client_options():
    """
    tcp客户端设置的IPv4和数据流 (使用者)
    :return:
    """
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #通道设置
    return sock

def tcp_server_options():
    """
    tcp服务器设置(管理者)
    :return:
    """
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    """
    level=socket.SOL_SOCKET 所在哪个协定层
    socket.SO_REUSEADDR 拜访选项名 这个是一个参数int类型
    """
    # SO_REUSEADDR端口开释后立刻就能够被再次应用 1代表开启就能够应用
    sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    print(sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR))

服务器比照客户端来说是管理者身份,治理客户端链接,所以会多一个 setsockopt,设置 socket 规定或者叫配置。而客户端是使用者,所以只有设置通道(拜访指标通道形式的)。

这个有个前置常识是 Tcp 握手和挥手,也是重要面试题,这里不做形容。
socket.SOL_SOCKET 是默认的代表你抉择的协定层,也就是 socket 都是这个。
socket.SO_REUSEADDR 是设置,TCP 挥手后还能被应用,只能设置 1 和 0。

sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 

这里批改为 2 或者-1 上面打印还是 1,这个也是 Python 做了大量的封装容纳的体现。
socket.SO_REUSEADDR 代表的是 optname 的管制形式,也就是挥手断开连接。
Http 是单次申请交互模式,也就是说你发一个数据流申请,会立刻被投递到服务器,进行验证非法,非法后应答后
Tcp 不是,Tcp 是发一组(多段数据流申请后),然而服务器不是立刻承受,是会拥挤在网络缓存区内,达到肯定数量在发给服务器。
所以这个也是初学者常常会遇到的,假如服务器齐全接管到客户端信息,客户端发了 10 次大小共 5000 个字节,服务器那边往往只会收到 3-4 次,大小总量也是 5000 个字节。这个能够在看完本文后,本人试试写个例子。

能够设置缓存区大小,缓存区大小会和 Tcp 重要概念无关,后面例子 plus:

def tcp_server_options():
    """
    tcp服务器设置
    :return:
    """
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    print(sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR))
    #设置发送缓存区包容单位
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 16 * 1024)
    print(f'Send -> {sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)}')
    print(f'Revice -> {sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)}')

socket.SO_RCVBUF 是由协定层决定的,协定层这里常量是通过协定层默认大小来示意(双关),65535+1 的 65536,当然这个默认大小能够批改的,通常倡议批改成 10 万,依据机器就地取材。
socket.SO_SNDBUF 就是 16 * 1024 的,那么如果不设置会是多少呢。在 socket 层有很多双关,默认也是 65536。
还能够设置通信阻塞,这个阻塞是服务器解决客户端 socket 申请的,阻塞是会解决完才会接管同一个客户端的下一条申请,然而高并发场景下,多个 work 线程的 Tcp 服务器个别都是非阻塞的,这里的设置是全局设置的,会对整个服务器以后启动失效。

sock.setblocking(False) #设置非阻塞的。
还能够设置超时工夫,然而不要画鱼加红烧肉这种做法,增加了超时工夫会和下面设置阻塞有一些抵触,会影响失常设置了缓存区大小等,所以不举荐应用。
这个和平时测试工具应用的 requests 外面 timeout 不一样。
惯例设置都曾经讲了,上面讲服务器如何去让客户端投递数据给他。

2.链接地址
基本上没差异,网络传输从 1 端到另外 1 端,要传输都须要有地址 接收者 iP+ 端口。
客户端须要晓得服务器的链接地址能力把音讯投递到正确的中央,服务器领有接收者 iP 会调配一个地址也就是端口,而后 bind 端口,监听链接到这个地址去治理客户端。

服务器还会有一个最大反对链接数,客户端是没有这个设置的,上面例子外面 max=5000,所以客户端和服务器关系是多对一的,最多反对 5000 个客户端链接到同个服务器。
看到下面,划重点关键字 bind 和 listen,给个例子,辨别客户端和服务器代码:

def server_listener(addr: tuple, max: int):
    """
    服务器监听 最大反对5000个链接数
    :param max:最大反对链接数
    :param addr:元组
    :return:
    """
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置挥手后能够应用
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(addr)
    # 最大反对max个链接数
    sock.listen(max)
    return sock

if __name__ == '__main__':
    server_listener(("0.0.0.0", 12580),5000)

http 的服务器因为包装的很好,并不会有这种设置,服务器都是一个监听客户端 fd 和轮询治理这些 fd 的。
客户端&服务器用同一套 socket options,这样服务器能力接管链接客户端的音讯,fd=sock.fileno()。

获取形式以及客户端链接代码,如下例子:

def create_client():
    """
    创立客户端
    :return:
    """
    # 客户端和服务器设置通道的socket必定是要一样的,否则链接不过去
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sockfd = sock.fileno()
    print(f"客户端fd={sockfd}")
    sock.connect(("127.0.0.1", 12580))
    return sock
if __name__ == '__main__':
    client = create_client()
    print(client)

客户端链接代码外面,地址不能是 0.0.0.1,本机测试也只能是 127.0.0.1。
connect_ex() 不为 0,会返回 error 的码,会在和协定号和谬误协定号串联一起的前面章节来讲。

服务器监听客户端 fd 的代码如下,外围函数是 accept():

def accept_client_connect(listener_sock):
    """
    服务器解决 确认客户端链接 外围办法是accept()
    :param listener_sock:服务器sock对象
    :return:
    """
    new_conn = listener_sock.accept()
    if new_conn == None:
        return
    sock, addr = new_conn
    # 服务器监听能够拿到那边拿sock的fd
    print(f"---accept_client_connection, sockfd={sock.fileno()}, addr={addr}")
    return sock

if __name__ == '__main__':
    sock = server_listener(("0.0.0.0", 12580), 5000)
    sock_ = accept_client_connect(sock)
    print(sock_)

最终打印

---accept_client_connection, sockfd=512, addr=('127.0.0.1', 14024)
<socket.socket fd=512, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 12580), raddr=('127.0.0.1', 14024)>

addr 端口就是服务器给客户端长期调配的端口,服务器就是通过字典治理,sockfd 和 addr[1],上面这段形容能够让其余语言也能够了解。

ClientInfo = {"client_fd":sockfd,"fd_port":addr[1]}
ClientGroup = []ClientInfo   
{"gateway_threads":ClientGroup} 

Workthread 分属不同作用,服务器外面的 gateway 服务 bind clientGroup 数组,这些细节前面章节会有具体的例子。

预报&总结

预报 socket 发包局部流程
step1: socket options(第二篇)
step2: 断开 socket,struct+pack 包 (数据结构)+ 压包 (数据结构在第一篇,第三篇是断开 socket 和 struct)
step3: 压缩的多种形式 (第四篇)
step4: 加密的多种形式 (第五篇)

总结

须要对 socket 设置做大量练习和了解更深刻的。其实 http 非 Python 得也有很多设置,倡议也能够深刻了解。
写法上都会反对客户端,服务器例子都有。
没有讲的 socket.shutdown 和 struct 这个库能够预习下。

> 本文首发于TesterHome社区,作者是资深游戏测试开发工程师陈子昂。用 Python 写网络编程共三篇,会陆续分享给大家。原文链接:https://testerhome.com/topics…


以上是明天的分享,你学废了吗~

想学习更多干货常识和前沿技术?

想结识测试行业大咖和业界精英?

欢送关注2022 MTSC大会(第十届中国互联网测试开发大会)

业界对MTSC大会的评估:落地、求实、有深度、重分享

中国互联网测试开发大会 Testing Summit China,是由TesterHome发动的软件测试开发行业技术会议。还有个别名:Make Testing Super Cool!

MTSC大会以软件品质保障体系和测试研发技术交换为次要目标,始于 2015 年,已胜利举办了九届。共有 1000+ 家企业,10000+ 测试工程师、测试经理、CTO 参会,受到了全行业的宽泛关注,是中国互联网质量保证行业的顶级会议。

为了保障议题品质,每年都会提前半年进行议题征集,再通过历时数月的审核,最终确定在大会分享的议题。MTSC 2022的议题还在征集中,诚邀各位资深测试技术专家、品质治理经理和测试新秀们投递议题!

提交议题形式

间接点击 https://www.wjx.top/vj/wZwCju… 进入投递入口,依照格局进行填写并提交即可。

议题截止工夫

为便于评审组有更充沛工夫进行评审及与讲师进行沟通优化,为宽广参会者出现更好的议题,议题投稿(可无 ppt)投递截止工夫提前为:2022年3月30日

议题征集评比流程

总体流程:案例提交  > 初审核定 > PPT提交 > 确认议题 > 会议演讲

成为分享讲师的收益

  1. 锤炼演讲能力,加强集体品牌
  2. 取得和业内专家面对面交换的机会,博采众长
  3. 晋升公司品牌,给本人的团队减少吸引力
  4. 获取收费的大会门票和材料:
    每位讲师都会获赠 1 张大会门票,大会后续的PPT和视频都会第一工夫给到讲师

MTSC 2022早鸟票已轻轻开售,点击理解详情。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于python:用-Python-写网络编程二

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址