python学习之网络编程

时间:2022-09-02 00:14:15
一、socket模块
    socket模块提供了底层的接口,通过socket模块可以实现不同计算机的通信
    ip+port定位了计算机中应用程序的具体位置,socket绑定ip+port来建立链接,socket的方法详情:
    socket(family, type, proto): socket函数创建一个socket对象,使用socket对象创建连接,
    family协议族,默认AF_INET,ipv4协议,type,socket类型,proto协议类型
    
    bind((ip, port)): 绑定服务器地址
    listen(n): 监听socket创建的链接, n代表指定连接队列数,
    connect(('127.0.0.1', 8080)): 连接到服务端
    accept():等待客户端连接,返回连接对象和客户端ip组成的元组
    recv(n): 接收数据,n代表接受固定的数据
    send(data): 发送数据
    
    例子:模拟客户端服务端通信
    server:
    #!/usr/bin/python
    # --*-- coding: utf-8 --*--
    
    import socket
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.bind(('127.0.0.1', 8080))
    
    phone.listen(5)
    
    print('starting...')
    
    conn, addr = phone.accept()
    print(conn)
    print('client addr: ', addr)
    print('ready to read msg')
    client_msg = conn.recv(1024)
    print('client msg: %s' %(client_msg))
    conn.send(client_msg.upper())
    conn.close()
    phone.close()
    
    client
    #!/usr/bin/pytthon
    # --*-- coding: utf-8 --*--
    import socket
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.connect(('127.0.0.1', 8080))
    
    phone.send('hello'.encode('utf-8'))
    
    back_msg = phone.recv(1024)
    print(back_msg.decode('gbk'))
    phone.close()
    
    模拟循环发送接收数据
    server
    import socket
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.bind(('127.0.0.1', 8080))
    phone.listen(5)
    
    while True:
        print('starting...')
        conn, addr = phone.accept()
        print('client addr ', addr)
        while True:
            try:
                client_msg = conn.recv(1024)
                if not client_msg: break
                print('client_msg: %s' %client_msg)
                conn.send(client_msg.upper())
            except Exception:
                break
        conn.close()
    phone.close()
    
    client
    import socket
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.connect(('127.0.0.1', 8080))
    
    while True:
        msg = input(">>: ")
        if not msg: continue
        phone.send(msg.encode('utf-8'))
        back_msg = phone.recv(1024)
        print(back_msg.decode('utf-8'))
    phone.close()
    
    模拟远程执行命令,并返回结果
    server
    import socket
    import subprocess
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.bind(('127.0.0.1', 8080))
    phone.listen(5)
    
    while True:
        print('starting...')
        conn,addr = phone.accept()
        print('client addr: ', addr)
        while True:
            try:
                cmd = conn.recv(1024)
                if not cmd: break
                res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                err = res.stderr.read()
                if err:
                    cmd_res = err
                else:
                    cmd_res = res.stdout.read()
                conn.send(cmd_res)
            except Exception:
                break
        conn.close()
    phone.close()
    
    client
    import socket
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.connect(('127.0.0.1', 8080))
    
    while True:
        cmd = input('>>: ').strip()
        if not cmd: continue
        phone.send(cmd.encode('utf-8'))
        back_msg = phone.recv(1024)
        print(back_msg.decode('gbk'))
    phone.close()
    
    粘包现象,数据包无规则断开,出现不希望的断开现象
    server
    from socket import *
    import time
    tcp_server = socket(AF_INET, SOCK_STREAM)
    tcp_server.bind(('127.0.0.1', 8080))
    tcp_server.listen(5)
    
    conn, addr = tcp_server.accept()
    res1 = conn.recv(5)
    res2 = conn.recv(5)
    res3 = conn.recv(7)
    print(res1.decode('gbk'))
    print(res2.decode('gbk'))
    print(res3.decode('gbk'))
    
    client
    from socket import *
    import time
    
    tcp_client = socket(AF_INET, SOCK_STREAM)
    tcp_client.connect(('127.0.0.1', 8080))
    
    tcp_client.send('hello world'.encode('utf-8'))
    time.sleep(5)
    tcp_client.send('egon666'.encode('utf-8'))
    
    解决粘包问题,使用struct模块,打包数据并解包数据
    例子:
    server
        import socket
        import subprocess
        import struct
        import json
        
        phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        phone.bind(('127.0.0.1', 8080))
        phone.listen(5)
        
        while True:
            print('starting...')
            conn, addr = phone.accept()
            print('client addr: ', addr)
            while True:
                try:
                    cmd = conn.recv(1024)
                    if not cmd:break
                    res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                    err = res.stderr.read()
                    if err:
                        cmd_res = err
                    else:
                        cmd_res = res.stdout.read()
        
                    head_dict = {'filename': None, 'hash': None, 'total_size': len(cmd_res)}
                    head_json = json.dumps(head_dict)
        
                    head_bytes = head_json.encode('utf-8')
                    print(struct.pack('i', len(head_bytes)))
                    conn.send(struct.pack('i', len(head_bytes)))
                    conn.send(head_bytes)
                    conn.send(cmd_res)
        
                except Exception:
                    break
            conn.close()
        phone.close()
        
        client
        import socket
        import struct
        import json
        
        phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        phone.connect(('127.0.0.1', 8080))
        
        while True:
            cmd = input('>>: ').strip()
            if not cmd: continue
            phone.send(cmd.encode('utf-8'))
            head_struct = phone.recv(4)
            #print(head_struct)
            head_len = struct.unpack('i', head_struct)[0]
            head_bytes = phone.recv(head_len)
            head_json = head_bytes.decode('utf-8')
            #print(head_json)
            head_dict = json.loads(head_json)
            #print(head_dict)
            total_size = head_dict['total_size']
            recv_size = 0
            data = b''
            while recv_size < total_size:
                recv_data = phone.recv(1024)
                data += recv_data
                recv_size += len(recv_data)
            print(data.decode('gbk'))
        phone.close()

  

本文出自 “linux技术” 博客,请务必保留此出处http://haoyonghui.blog.51cto.com/4278020/1939996