zoukankan      html  css  js  c++  java
  • 网络编程基础之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() # 关机

      

  • 相关阅读:
    LeetCode Count of Range Sum
    LeetCode 158. Read N Characters Given Read4 II
    LeetCode 157. Read N Characters Given Read4
    LeetCode 317. Shortest Distance from All Buildings
    LeetCode Smallest Rectangle Enclosing Black Pixels
    LeetCode 315. Count of Smaller Numbers After Self
    LeetCode 332. Reconstruct Itinerary
    LeetCode 310. Minimum Height Trees
    LeetCode 163. Missing Ranges
    LeetCode Verify Preorder Serialization of a Binary Tree
  • 原文地址:https://www.cnblogs.com/schut/p/8671926.html
Copyright © 2011-2022 走看看