• 简单的套接字通信加通信循环修复bug链接循环模拟ssh远程执行命令


    客户端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、打电话
    phone.connect(("127.0.0.1", 8080))  # phone相当于服务端的conn
    
    # 3、发、收消息
    phone.send('hello'.encode("utf-8"))
    data = phone.recv(1024)
    print(data)
    
    # 4、关闭
    phone.close()
    

    服务端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、绑定手机卡
    phone.bind(("127.0.0.1", 8080))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
    
    # 3、开机
    phone.listen(5)   # 5代表最大挂起连接数
    
    # 4、等电话连接
    print("starting...")
    conn, client = phone.accept()
    
    # 5、收、发消息
    data = conn.recv(1024)  # 收1024个字节,接受数据的最大数。单位是bytes
    print("客户端的数据", data)
    conn.send(data.upper())
    
    # 6、挂电话
    conn.close()
    
    # 7、关机
    phone.close() 

    加循环(通信循环)

    客户端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、打电话
    phone.connect(("127.0.0.1", 8080))  # phone相当于服务端的conn
    
    # 3、发、收消息
    while True:
        msg = input(">> ").strip()
        phone.send(msg.encode("utf-8"))
        data = phone.recv(1024)
        print(data)
    
    # 4、关闭
    phone.close()
    

    服务端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、绑定手机卡
    phone.bind(("127.0.0.1", 8080))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
    
    # 3、开机
    phone.listen(5)   # 5代表最大挂起连接数
    
    # 4、等电话连接
    print("starting...")
    conn, client = phone.accept()
    
    # 5、收、发消息
    while True:
        data = conn.recv(1024)  # 收1024个字节,接受数据的最大数。单位是bytes
        print("客户端的数据", data)
        conn.send(data.upper())
    
    # 6、挂电话
    conn.close()
    
    # 7、关机
    phone.close()
    

     


     修复bug

    1、客户端单方面断开,服务端: linux 解决办法:if not data:break
             windows 解决办法:try...except

    send 可以发 空 # 发给了os的内存 在调用网卡 发送数据
    recv 不可以 收空 # 到了os的内存 在传给了应用程序内存
    所以 客户端 就卡住了 if not msg:continue 卡住原因 os 不会发''(空)数据

    
    

      2、端口已存在,重用

    问题:

     这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址

    解决办法1:

    #加入一条socket配置,重用ip和端口
    phone=socket(AF_INET,SOCK_STREAM)
    phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
    phone.bind(('127.0.0.1',8080))


    解决办法2:

    发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
    vi /etc/sysctl.conf


    编辑文件,加入以下内容:
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30

    然后执行 /sbin/sysctl -p 让参数生效。

    net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;

    net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

    net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。

    net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

     

    解决办法3:

    解决前面启动多个socket程序,占用系统端口问题。(命令提示符cmd)
    linux: pkill -9 python
    windows: taskkill python (打开任务管理器,找到python,关闭)


    客户端
    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、打电话
    phone.connect(("127.0.0.1", 8080))  # phone相当于服务端的conn
    
    # 3、发、收消息
    while True:
        msg = input(">> ").strip()
        if not msg:
            continue
        phone.send(msg.encode("utf-8"))
        data = phone.recv(1024)
        print(data.decode("utf-8"))
    
    # 4、关闭
    phone.close()

     服务端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # (如果机器中存在,重新用端口)应对端口占用报错情况
    # 2、绑定手机卡
    phone.bind(("127.0.0.1", 8080))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
    
    # 3、开机
    phone.listen(5)   # 5代表最大挂起连接数
    
    # 4、等电话连接
    print("starting...")
    conn, client = phone.accept()  # conn套接字对象
    
    # 5、收、发消息
    while True:
        try:
            data = conn.recv(1024)  # 收1024个字节,接受数据的最大数。单位是bytes
           # if not data: break         # 仅适用于Linux操作系统(客户端单方面断开),win 用try...except
            print("客户端的数据", data)
            conn.send(data.upper())
        except ConnectionRefusedError:
            break
    
    # 6、挂电话
    conn.close()
    
    # 7、关机
    phone.close()
    

      


     加上链接循环

    服务端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # (如果机器中存在,重新用端口)应对端口占用报错情况
    # 2、绑定手机卡
    phone.bind(("127.0.0.1", 8080))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
    
    # 3、开机
    phone.listen(5)   # 5代表最大挂起连接数
    
    # 4、等电话连接
    print("starting...")
    while True:  # 循环链接
        conn, client = phone.accept()  # conn套接字对象
    
        # 5、收、发消息
        while True:    # 通讯循环
            try:
                data = conn.recv(1024)  # 收1024个字节,接受数据的最大数。单位是bytes
               # if not data: break  # 仅适用于Linux操作系统(客户端断开),win 用try...except
                print("客户端的数据", data)
                conn.send(data.upper())
            except ConnectionRefusedError:
                break
    
        # 6、挂电话
        conn.close()
    
    # 7、关机
    phone.close()
    

    客户端1

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、打电话
    phone.connect(("127.0.0.1", 8080))  # phone相当于服务端的conn
    
    # 3、发、收消息
    while True:
        msg = input(">> ").strip()
        if not msg:
            continue
        phone.send(msg.encode("utf-8"))
        data = phone.recv(1024)
        print(data.decode("utf-8"))
    
    # 4、关闭
    phone.close()
    

    客户端2

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、打电话
    phone.connect(("127.0.0.1", 8080))  # phone相当于服务端的conn
    
    # 3、发、收消息
    while True:
        msg = input(">> ").strip()
        if not msg:
            continue
        phone.send(msg.encode("utf-8"))
        data = phone.recv(1024)
        print(data.decode("utf-8"))
    
    # 4、关闭
    phone.close()
    

     模拟ssh远程执行命令

    # windows
    dir:查看某一个文件夹下的子文件名与文件夹名
    ipconfig:查看本地网卡的ip信息
    tasklist:查看运行的进程


    # Linux
    ls:查看某一个文件夹下的子文件名与文件夹名
    ifconfig:查看本地网卡的ip信息(查看网卡的信息)
    ps aux:查看运行的进程


    在机器上执行系统命令
    # import os
    # res = os.system( ) # 只能拿到执行成功与否的标志(0代表成功,非零代表不成功)


    import subprocess
    obj = subprocess.Popen("dir/",shell = True,stdout = subprocess.PIPE, stderr = subprocess.PIPE) #stdout命令正确结果


    print("stdout", obj.stdout.read().decode("gbk")) # 打印出来结果(解码linux:utf-8,windows:GBK)
    print("stderr", obj.stderr.read().decode("gbk")) # 打印出来结果(解码linux:utf-8,windows:GBK)

    # import os
    # res = os.system('dir d:')
    # print(os.system('dir d:'))
    # # print(res)
    
    import subprocess
    obj=subprocess.Popen('dir d:ss',shell=True,
                     stdout=subprocess.PIPE,  # 正确的结果
                     stderr=subprocess.PIPE)  # 错误的结果
    print(obj)  # 执行的结果 是bytes
    print('stdout 1--:',obj.stdout.read().decode('gbk'))  # linux 是 utf-8  windows 是 gbk
    print('stdout 2--:',obj.stdout.read().decode('gbk'))  # 因为管道没有了
    print('stdout 3--:',obj.stderr.read().decode('gbk'))  # 错误管道里有 原因 拿不到数据
    

    服务端

    import socket
    import subprocess
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # (如果机器中存在,重新用端口)应对端口占用报错情况
    # 2、绑定手机卡
    phone.bind(("127.0.0.1", 9900))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
    
    # 3、开机
    phone.listen(5)   # 5代表最大挂起连接数
    
    # 4、等电话连接
    print("starting...")
    while True:  # 循环链接
        conn, client = phone.accept()  # conn套接字对象
    
    # 5、收、发消息
        while True:    # 通讯循环
            try:
                # a、接收命令  (命令:执行系统命令)
                cmd = conn.recv(1024)  # 收1024个字节,接受数据的最大数。单位是bytes
               # if not data: break  # 仅适用于Linux操作系统(客户端断开),win 用try...except
                # b、执行命令,拿到结果
                obj = subprocess.Popen(cmd.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                stdout = obj.stdout.read()
                stderr = obj.stderr.read()
    
                # c、把命令的结果返回给客户端
                print(len(stdout)+len(stderr))
                conn.send(stdout+stderr)  # 加是重新申请了一块内存地址,不是在原来地方变动(是一个可以优化的点)
    
            except ConnectionRefusedError:
                break
    
    # 6、挂电话
        conn.close()
    
    # 7、关机
    phone.close()
    

    客户端

    import socket
    
    # 1、买手机
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2、打电话
    phone.connect(("127.0.0.1", 9900))  # phone相当于服务端的conn
    
    # 3、发、收消息
    while True:
        # a、发命令
        cmd = input(">> ").strip()
        if not cmd:
            continue
        phone.send(cmd.encode("utf-8"))
    
        # b、拿命令结果并打印
        data = phone.recv(1024)   # 1024是个坑
        print(data.decode("gbk"))   # 系统发回的结果
    
    # 4、关闭
    phone.close()
    

      

      

    
    
  • 相关阅读:
    Django之Cookie与Session
    Django之分页器
    Django基础之Ajax
    算法 【第八章】斐波那契数列
    算法 【第七章】贪心算法找零问题
    算法 【第六章】数据结构相关知识
    算法 【第五章】常用排序算法
    算法 【第四章】堆的简单介绍
    算法 【第三章】树和二叉树简介
    算法 【第二章】列表查找以及二分查找
  • 原文地址:https://www.cnblogs.com/fantsaymwq/p/10050996.html
Copyright © 2020-2023  润新知