• 网络编程基础之Socket套接字简单应用


    一、Socket套接字实现通信循环

      所谓通信循环,简单理解就是客户端可以给服务端循环发送信息并获得反馈的过程。

      1、基础版

        通信循环的程序分为两部分,即两个python模块,分别为客户端.py和服务端.py

        第一部分:服务端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    
    phone.bind(('127.0.0.1',3301))  # 绑定指定IP和端口
    
    phone.listen(5) # 开机,监听
    
    conn,client = phone.accept() # 等待链接,并将获取的链接赋给conn和client,conn是另一个套接字对象
    
    while True:
        data = conn.recv(1024)   # 收讯息
        print('收到来自客户端的讯息:',data)
        conn.send(data.title()) # 发送讯息
    
    conn.close() # 关闭链接
    
    phone.close() # 关机

        第二部分:客户端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    # SOCK_STREAM 指的是TCP协议(或称流式协议)
    # SOCK_DGRAM 指的是UDP协议(或称数据报协议)
    phone.connect(('127.0.0.1',3301)) # 链接指定IP和端口的服务端
    while True:
        mes = input('在此输入>>:').strip()
        phone.send(mes.encode('utf-8')) # 发讯息
        data = phone.recv(1024)                 # 收讯息
        print('收到来自服务端的消息:',data.decode('utf-8'))
    phone.close()     # 关机

      

      2、改进版

        上面的程序代码其实是存在bug的,比如没有对用户未输入和输入错误等进行异常处理,改进后的程序代码如下:

        第一部分:服务端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 端口重用, 解决程序关闭后端口仍然占用的情况
    
    phone.bind(('127.0.0.1',3301))  # 绑定指定IP和端口
    
    phone.listen(5) # 开机,监听
    
    conn,client = phone.accept() # 等待链接,并将获取的链接赋给conn和client,conn是另一个套接字对象
    
    while True:
        try:
            data = conn.recv(1024)   # 收讯息
            if not data:break  # 仅适用于linux系统
            print('收到来自客户端的讯息:',data)
            conn.send(data.title()) # 发送讯息
        except ConnectionResetError: # 适用于windows系统
            break
    
    conn.close() # 关闭链接
    
    phone.close() # 关机
    View Code

        第二部分:客户端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    
    phone.connect(('127.0.0.1',3301)) # 链接指定IP和端口的服务端
    while True:
        mes = input('在此输入>>:').strip()
        if not mes:continue  # 防止未输入
        phone.send(mes.encode('utf-8')) # 发讯息
        data = phone.recv(1024)                 # 收讯息
        print('收到来自服务端的消息:',data.decode('utf-8'))
    phone.close()     # 关机
    View Code

        

    二、Socket套接字实现链接循环 

      现在我们不满足于简单地通信循环了,我们的需求增加了链接循环,要求程序不光可以进行通信循环,还可以进行链接循环。

      链接循环:我的理解就是服务端一直保持运行,而客户端可以在多个间切换分别与服务端进行连接(简而言之,就是多个客户端与一个服务端间的通信)。

      增加功能后,改变的主要是服务端.py,程序同样是分为两部分。

      第一部分:服务端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 端口重用, 解决程序关闭后端口仍然占用的情况
    
    phone.bind(('127.0.0.1',3301))  # 绑定指定IP和端口
    
    phone.listen(5) # 开机,监听
    while True:  # 链接循环
        conn,client = phone.accept() # 等待链接,并将获取的链接赋给conn和client,conn是另一个套接字对象
        while True: # 通信循环
            try:
                data = conn.recv(1024)   # 收讯息
                if not data:break  # 仅适用于linux系统
                print('收到来自客户端的讯息:',data)
                conn.send(data.title()) # 发送讯息
            except ConnectionResetError: # 适用于windows系统
                break
    
        conn.close() # 关闭链接
    
    phone.close() # 关机
    
    '''
    同时有多个客户端发送请求时,链接循环条件下服务端只能一次执行一个,服务端可以一直执行,只有当此客户端结束运行,
    才能继续执行另一客户端的请求,以此类推客户端1结束后,客户端2执行,2结束,3才执行
    '''

      第二部分:客户端.py

      客户端1.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    
    phone.connect(('127.0.0.1',3301)) # 链接指定IP和端口的服务端
    while True:
        mes = input('在此输入>>:').strip()
        if not mes:continue  # 防止未输入
        phone.send(mes.encode('utf-8')) # 发讯息
        data = phone.recv(1024)                 # 收讯息
        print('收到来自服务端的消息:',data.decode('utf-8'))
    phone.close()     # 关机

      客户端2.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    
    phone.connect(('127.0.0.1',3301)) # 链接指定IP和端口的服务端
    while True:
        mes = input('在此输入>>:').strip()
        if not mes:continue  # 防止未输入
        phone.send(mes.encode('utf-8')) # 发讯息
        data = phone.recv(1024)                 # 收讯息
        print('收到来自服务端的消息:',data.decode('utf-8'))
    phone.close()     # 关机
    View Code

      客户端3.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化了一个对象,phone即是一个套接字对象
    
    phone.connect(('127.0.0.1',3301)) # 链接指定IP和端口的服务端
    while True:
        mes = input('在此输入>>:').strip()
        if not mes:continue  # 防止未输入
        phone.send(mes.encode('utf-8')) # 发讯息
        data = phone.recv(1024)                 # 收讯息
        print('收到来自服务端的消息:',data.decode('utf-8'))
    phone.close()     # 关机
    View Code

    三、ssh远程执行命令

      1、几点预备知识

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import os
    
    '''
    windows下测试:
        dir:查看某一个文件夹下的子文件名和文件夹名
        ipconfig :查看本地网卡的IP信息
        tasklist:查看运行的进程
    '''
    # 执行系统命令,并拿到命令的结果
    
    res = os.system('dir')
    res = os.system('ipconfig')
    print('命令结果:',res) # 命令结果: 0 ,0表示执行成功,非0表示失败
    
    import subprocess
    
    obj = subprocess.Popen('dir',shell=True,
                           stdout=subprocess.PIPE, # 获取'dir'命令执行正确时的返回信息
                           stderr=subprocess.PIPE) # # 获取错误命令执行时的返回信息
    
    print(obj) # <subprocess.Popen object at 0x00000252715E70F0>
    print('正确时执行stdout>>:',obj.stdout.read().decode('gbk')) # 因为执行的是windows系统的命令,默认编码是gbk, read()获取的是bytes数据,需要decode解码转为操作系统可读的
    print('错误时执行stderr>>:',obj.stderr.read().decode('gbk')) # 如果是linx系统,则默认是utf-8

      2、核心程序仍然分为两部分

        服务端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    
    import socket
    import subprocess
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 实例化一个套接字对象
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 端口重用,解决程序结束而端口仍被占用的情况
    
    phone.bind(('127.0.0.1',3301)) # 绑定IP和端口
    
    phone.listen(5) # 监听
    
    while True:
        conn,client = phone.accept() # 获取链接对象和IP、端口
    
        while True: # 通讯循环
            try:  # 适用于windows系统
                # 1、接受命令
                cmd = conn.recv(1024)
                if not cmd:break # 适用于linux系统
                print('收到来自客户端的命令:',cmd.decode('gbk'))  # 打印接收到的命令
                # 2、执行命令
                obj = subprocess.Popen(cmd.decode('gbk'),shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
                print(obj)
                # 3、返回命令执行后的结果
                stdout = obj.stdout.read() # 命令执行正确时结果
                stderr = obj.stderr.read() # 错误命令执行的结果
                conn.send(stdout+stderr)   # 返回执行命令的结果
            except ConnectionResetError:
                break
        conn.close()
    
    phone.close()

        客户端.py

    #!/usr/bin/env python3
    #-*- coding:utf-8 -*-
    # write by congcong
    import socket
    
    phone = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM) # 创建套接字对象
    
    phone.connect(('127.0.0.1',3301)) # 建立链接
    
    while True: # 通信循环
        cmd = input('输入命令>>:').strip()
        if not cmd:continue
        phone.send(cmd.encode('gbk')) # 发送命令
        data = phone.recv(1024)  # 接收信息
        print('接收来自服务端的信息:',data.decode('gbk')) # 打印接收的信息
    
    phone.close() # 关机

      

  • 相关阅读:
    解决上传文件大小限制 PHP+Apache
    PHP中ftp的连接与操作
    python 批量修改文件名
    pytorch 断点续训练
    图片的读取
    tensor 类型转换
    卷积网络提取图像特征
    U盘拷贝数据到服务器
    1*1卷积核的作用
    skimage
  • 原文地址:https://www.cnblogs.com/schut/p/8671926.html
Copyright © 2020-2023  润新知