zoukankan      html  css  js  c++  java
  • [ python ] 网络编程(1)

    在本地电脑上有两个python文件 regist.py 、login.py 一个注册,一个登录。这两个python一个是写用户信息,一个是读用户信息,要怎么做呢?

    通过之前的知识,我们可以通过 regist.py 序列化一个数据并持久保存到磁盘上,然后 login.py 在取读取这个文件就行。

    但是,当这两个文件在不同的主机上时,我们就需要通过网络编程来实现,类似qq、网盘、微信。

    osi 七层协议

    在这七层中,我们应该明确:

    每层运行常用物理设备:

    每层运行常见的协议

    要记牢:ip是在网络层,tcp、udp等协议是在传输层。

    socket概念

    理解 socket

    从表现形式来讲,socket就是 ip:port,从设计模式来讲,socket其实就是一个门面模式,它把复杂的tcp/ip协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。

    从python的角度来看,socket就是一个模块,我们通过调用模块中已经实现的方法建立两个进程之间的连接和通信。socket = ip:port  ip 用来标识互联网中的一台主机的位置,而port是用来标识这台主机上的一个应用程序,所以我们只要确立了ip和port就能找到一个应用程序,并且使用socket模块来与之通信。

    tcp协议与udp协议

    tcp( Transmission Control Protocol ): 可靠的、面向连接的协议、传输效率低全双工通信、面向字节流。使用tcp应用:web浏览器;电子邮件、文件传输程序。
    udp( User Datagram Protocol ): 不可靠的、无连接的服务,传输效率高,一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。
    使用udp的应用:域名系统;视频流;ip语音

    套接字(socket)使用

    1. 基于tcp协议的socket

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

    sever端

    import socket
    
    sock = socket.socket()  # 创建 socket 对象
    sock.bind(('127.0.0.1', 8080))  # 绑定ip和port
    sock.listen(5)  # 建立监听链接
    conn, addr = sock.accept()  # 阻塞,随时准备接收客户端链接
    res = conn.recv(1024)   # 阻塞,等待接收客户端发送过来的数据
    conn.send(b'hello client.') # 向客户端发送信息
    conn.close()    # 关闭本次链接
    sock.close()    # 关闭服务器socket

    client端

    import socket
    
    sock = socket.socket()  # 创建 socket 对象
    sock.connect(('127.0.0.1', 8080))   # 去连接服务端的socket
    sock.send(b'hello server.') # 发送信息给服务端的socket
    res = sock.recv(1024)   # 接收服务端socket发送过来的信息
    print(res)
    sock.close()    # 关闭客户端连接

    总结:
    server端:
    (1)创建socket对象
    (2)绑定ip:port, 这里 ip为str类型,port为int类型
    (3)建立socket监听
    (4)准备接收客户端连接并返回socket连接信息和addr信息
    (5)conn.send 发送信息、 conn.recv 接收消息
    (6)先关闭连接,再关闭 socket

    client端:

    (1)创建socket对象
    (2)通过 connect 尝试去连接服务端的socket
    (3)sock.send 发送消息、sock.recv 接收消息
    (4)关闭连接的socket

    2. 基于UDP协议的socket

    udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接

    server端

    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM)  # 创建一个服务器的套接字,这里必须要定义 type=socket.SOCK_DGRAM
    udp_sk.bind(('127.0.0.1', 8080))    # 绑定服务器套接字
    msg, addr = udp_sk.recvfrom(1024)   # udp服务器端第一次通信必须是接收信息
    print(msg)
    udp_sk.sendto(b'hello, client.', addr)  # 发送信息
    udp_sk.close()  # 关闭服务器套接字



    client端

    import socket
    ip_port = ('127.0.0.1', 8080)   # 建立ip、port元组
    udp_sk = socket.socket(type=socket.SOCK_DGRAM)  # 创建一个服务器的套接字,这里必须要定义 type=socket.SOCK_DGRAM
    udp_sk.sendto(b'hello server.', ip_port)    # 发送消息给服务器端,在udp中第一次交互由客户端发起
    back_msg, addr = udp_sk.recvfrom(1024)  # 接收数据包括(服务器端数据,套接字信息)
    print(back_msg)
    udp_sk.close()  # 关闭套接字

    练习:使用 socket 模块实现 服务端 和 客户端 连接并执行命令。

    import socket
    import subprocess
    
    sk_server = socket.socket() # 创建 socket对象
    sk_server.bind(('localhost', 8080)) # 建立socket
    sk_server.listen(5) # 开启监听
    conn, addr = sk_server.accept() # 接收客户端信息
    while True:
        command = conn.recv(1024).decode()
        cmd_res = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) # 执行命令
        stdout = cmd_res.stdout.read()
        stderr = cmd_res.stderr.read()
        result = stdout if stdout else stderr
        res_size = len(result)  # 统计命令执行结果大小
        print(res_size)
        conn.sendall(str(res_size).encode())    # 首先发送命令结果大小
        response = conn.recv(1024).decode()
        conn.sendall(result)    # 发送命令结果
    server.py
    import socket
    
    sk_client = socket.socket()
    sk_client.connect(('localhost', 8080))
    while True:
        cmd = input('>>>').strip()
        if not cmd: continue
        sk_client.sendall(cmd.encode())
        res_size = int(sk_client.recv(1024).decode())   # 接收命令结果大小
        sk_client.sendall(b'000')
        revice_size = 0
        while res_size != revice_size:  # 通过命令大小循环获取数据
            data = sk_client.recv(1024)
            revice_size += len(data)
            print(data.decode('gbk'))
    client.py
  • 相关阅读:
    过河问题 贪心
    喷水装置2 贪心
    喷水装置 贪心算法
    大红数星星 图论 XD网络赛
    Bi-shoe and Phi-shoe 欧拉函数 素数
    c++ 打飞机游戏开发日志
    POJ 1129 Channel Allocation DFS 回溯
    POJ 2676 Sudoku
    LibreOJ #100. 矩阵乘法
    BZOJ 1009: [HNOI2008]GT考试
  • 原文地址:https://www.cnblogs.com/hukey/p/10163789.html
Copyright © 2011-2022 走看看