美文网首页
2019-10-27

2019-10-27

作者: 剑飞张 | 来源:发表于2019-12-01 23:33 被阅读0次

    title: python socket编程入门
    date: 2019-12-01 17:11:26
    tags:

    • python
    • 计算机网络

    [toc]

    socket

    socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。

    基本上,Socket 是任何一种计算机网络通讯中最基础的内容。例如当你在浏览器地址栏中输入 http://www.cnblogs.com/ 时,你会打开一个套接字,然后连接到 http://www.cnblogs.com/ 并读取响应的页面然后然后显示出来。而其他一些聊天客户端如 QQ 和微信也是类似。任何网络通讯都是通过 Socket 来完成的。<del>(从操作系统角度来看,socket 比进程的 pid 级别还低,socket 是识别进程通信间的进程,pid 是识别所有进程)<del>

    socket和file的区别:

    1、file模块是针对某个指定文件进行【打开】【读写】【关闭】
    
    2、socket模块是针对 服务器端 和 客户端 Socket 进行【打开】【读写】【关闭】
    

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

    socket

    工作原理(流程)

    工作流程

    可以看到服务端必须先运行等待客户端连接。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞(阻塞这个进程),等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

    python 的 socket 模块

    Python 的 socket 模块提供了使用 Berkeley sockets API 的接口。

    主要学习了以下 API:

    • socket()
    • bind()
    • listen()
    • accept()
    • connect()
    • send()
    • recv()
    • close()

    Python 提供了和 C 语言一致且方便的 API。

    tcp socket

    tcp 是一个可靠的,有序的协议。网络总是会尽最大的努力去传输完整数据(往往不尽人意)。

    网络设备(比如:路由器、交换机)都有带宽限制,或者系统本身的极限。它们也有 CPU、内存、总线和接口包缓冲区,就像我们的客户端和服务器。TCP 消除了对于丢包、乱序以及其它网络通信中通常出现的问题的顾虑。


    tcp 工作的流程

    左边表示服务器,右边表示客户端。

    客户端调用 connect() 方法来建立与服务器的链接,并开始三次握手。握手很重要是因为它保证了网络的通信的双方可以到达,也就是说客户端可以正常连接到服务器,反之亦然。

    上图中间部分往返部分表示客户端和服务器的数据交换过程,调用了 send() 和 recv()方法。

    • 简单tcp的 server 端代码:
    import socket
    
    HOST = '127.0.0.1'  # 标准的回环地址 (localhost)
    PORT = 65432        # 监听的端口 (非系统级的端口: 大于 1023)
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print('Connected by', addr)
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    

    调用 socket() 时传入的 socket 地址族参数 socket.AF_INET 表示因特网 IPv4 地址族,SOCK_STREAM 表示使用 TCP 的 socket 类型,协议将被用来在网络中传输消息。

    listen() 方法有一个 backlog 参数。它指定在拒绝新的连接之前系统将允许使用的 未接受的连接 数量。从 Python 3.5 开始,这是可选参数。如果不指定,Python 将取一个默认值。很明显,backlog起保护作用,防止服务器过载。

    accept() 方法阻塞并等待传入连接。当一个客户端连接时,它将返回一个新的 socket 对象,对象中有表示当前连接的 conn 和一个由主机、端口号组成的 IPv4/v6 连接的元组。和监听一个 socket 不同的是后者只用来授受新的连接请求,而 accept() 则是得到一个新的 socket 对象。

    • 简单 tcp 的 client 端代码:
    import socket
    
    HOST = '127.0.0.1'  # 服务器的主机名或者 IP 地址
    PORT = 65432        # 服务器使用的端口
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((HOST, PORT))
        s.sendall(b'Hello, world')
        data = s.recv(1024)
    
    print('Received', repr(data))
    

    与服务器程序相比,客户端程序简单很多。它创建了一个 socket 对象,连接到服务器并且调用 s.sendall() 方法发送消息,然后再调用 s.recv() 方法读取服务器返回的内容并打印出来。

    运行结果:


    简单tcp编程结果

    udp socket

    使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,不保证数据的一定到达。

    虽然用UDP传输数据不可靠,但它的优点是和TCP比,速度快,对于不要求可靠到达的数据,就可以使用UDP协议。

    • 简单 UDP 的编程实现 server.py
    import socket
    
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        s.bind(('127.0.0.1',8080))
        while True:
            conn,addr = s.recvfrom(1024)
            print('Received from %s:%s.' % addr)
            s.sendto(b'Hello, %s!' % conn, addr)
    

    UDP 的服务端仅需要监听端口的数据,而不需要监听是否会有新的连接请求,只需要数据来临就接收。

    • 简单 UDP 的编程实现 client.py
    import socket
    
    with socket.socket(socket.AF_INET,socket.SOCK_DGRAM) as s:
        for data in [b'Michael', b'Tracy', b'Sarah']:
            s.sendto(data, ('127.0.0.1', 8080))
        # 接收数据:
            print(s.recv(1024).decode('utf-8'))
    

    而 UDP 的客户端更加简单,只需要拿到数据之后往服务器地址的端口直接发送就行。

    相关文章

      网友评论

          本文标题:2019-10-27

          本文链接:https://www.haomeiwen.com/subject/tcwmvctx.html