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