简单的套接字通信加通信循环修复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()

  

  


原文地址:https://www.cnblogs.com/fantsaymwq/p/10050996.html