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

浙公网安备 33010602011771号