# server
import asyncore # 源码分析很有用
import struct
import threading
import socket
class CJSocket(asyncore.dispatcher):
def __init__(self, sock, maps):
super(CJSocket, self).__init__(sock=sock, map=maps)
self.send_buffer = b''
def writable(self):
return len(self.send_buffer) > 0
def handle_write(self):
sent = self.send(self.send_buffer)
self.send_buffer = self.send_buffer[sent:]
def auto_send(self, lst1, lst2):
buff = b''
for i in range(len(lst1)):
buff += struct.pack(lst1[i], lst2[i])
self.send_buffer += buff
def readable(self):
return True
def handle_read(self):
# data = self.recv(819 2)
data = self.recv(4)
data += self.recv(struct.unpack('!I', data[0:4])[0] - 4)
if len(data) < 12:
return
sum_len = struct.unpack('!I', data[0:4])[0] # 总长
cmd_id = struct.unpack('!I', data[4:8])[0] # 命令
seq_id = struct.unpack('!I', data[8:12])[0] # 序列号
print('sum_len:{sum_len} cmd_id:{cmd_id} seq_id:{seq_id}'.format(sum_len=sum_len, cmd_id=cmd_id, seq_id=seq_id))
if cmd_id == 1: # 回复hello
typist = ['!I', '!I', '!I', '!I', '!5s']
values = [21, 2, seq_id, 5, b'hello']
self.auto_send(typist, values)
elif cmd_id == 3: # 回复bye
msg_len = struct.unpack('!I', data[12:16])[0]
msg = struct.unpack('!'+str(msg_len)+'s', data[16:16+msg_len])[0]
msg = msg.decode()
print('get the msg', msg)
msg = list(msg)
msg.reverse()
msg = ''.join(msg)
msg = msg.encode()
typist = ['!I', '!I', '!I', '!I', '!'+str(msg_len)+'s']
values = [16+msg_len, 4, seq_id, msg_len, msg]
self.auto_send(typist, values)
elif cmd_id == 5: # 回复bye
typist = ['!I', '!I', '!I', '!I', '!3s']
values = [19, 6, seq_id, 3, b'bye']
self.auto_send(typist, values)
def handle_close(self) -> None:
self.close()
class CJServer(asyncore.dispatcher):
def __init__(self, host, port, maps):
asyncore.dispatcher.__init__(self, sock=None, map=maps)
self.create_socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
self.map = maps
# self.map[self._fileno] = self
self.set_reuse_addr()
self.bind((host, port))
self.listen(5) # listen(n)传入的值, n表示的是服务器拒绝(超过限制数量的)连接之前,操作系统可以挂起的最大连接数量。
self.handle_list = []
def handle_accepted(self, sock, adds):
self.handle_list.append(CJSocket(sock=sock, maps=self.map))
print('现在CJ监听列表的socket是:', self.map)
def handle_close(self):
for i in range(len(self.handle_list)):
self.handle_list[i].handle_close()
self.close()
class CJThread:
cnt = 0
cjmap = {}
def __init__(self, ip, port):
self.ip = ip
self.port = int(port)
self.CJ = None
self.thread = None
def start(self):
CJThread.cnt += 1
print('CJThread.cnt:', CJThread.cnt)
self.CJ = CJServer(self.ip, self.port, CJThread.cjmap)
print('现在的CJ监听列表:', CJThread.cjmap)
if CJThread.cnt == 1:
self.thread = threading.Thread(target=asyncore.loop, kwargs={'timeout': 1, 'use_poll': True, 'map': CJThread.cjmap})
self.thread.start()
def stop(self):
self.CJ.handle_close()
CJThread.cnt -= 1
print('CJThread.cnt:', CJThread.cnt)
print('现在的CJ监听列表:', CJThread.cjmap)
CJThread1 = CJThread('127.0.0.1', 9999)
CJThread1.start()
input()
# CJThread2 = CJThread('127.0.0.1', 8888)
# CJThread2.start()
# input()
# CJThread1.stop()
# input()
# CJThread2.stop()
# input()
# CJThread1 = CJThread('127.0.0.1', 8888)
# CJThread1.start()
# input()
# CJThread2 = CJThread('127.0.0.1', 9999)
# CJThread2.start()
# input()
CJThread1.stop()
# input()
# CJThread2.stop()
# input()
# client
import asyncore
import socket
import struct
class HTTPClient(asyncore.dispatcher):
def __init__(self, host):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, 9999))
self.buffer = b''
typist = ['!I', '!I', '!I']
values = [12, 1, 6]
for i in range(len(typist)):
self.buffer += struct.pack(typist[i], values[i])
typist = ['!I', '!I', '!I', '!I', '!4s']
values = [20, 3, 7, 4, b'abcd']
for i in range(len(typist)):
self.buffer += struct.pack(typist[i], values[i])
typist = ['!I', '!I', '!I']
values = [12, 5, 8]
for i in range(len(typist)):
self.buffer += struct.pack(typist[i], values[i])
def handle_connect(self):
print('connect success')
def handle_close(self):
self.close()
print('close success')
def readable(self) -> bool:
return True
def handle_read(self):
data = self.recv(4)
data += self.recv(struct.unpack('!I', data[0:4])[0] - 4)
print(data)
def writable(self):
return len(self.buffer) > 0
def handle_write(self):
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
client = HTTPClient('127.0.0.1')
asyncore.loop()
多线程两种写法
# 一、直接使用threading
import threading
def action(maxs):
for j in range(maxs):
print(threading.current_thread().getName() + " " + str(j))
t1 = threading.Thread(target=action, name='t1', args=(4,))
t2 = threading.Thread(target=action, name='t2', args=(5,))
for i in range(10):
print(threading.current_thread().getName() + " " + str(i))
if i == 3:
t1.start()
t2.start()
print('主线程执行完成!')
t1.join()
t2.join()
# 二、继承使用threading
class MyThread(threading.Thread): # 可维护成员cnt,可获得线程返回值self.result
cnt = 0
def __init__(self, target, args=()):
super(MyThread, self).__init__()
self.result = "default result"
self.target = target
self.args = args
def run(self):
MyThread.cnt += 1
print('MyThread.cnt', MyThread.cnt)
self.result = self.target(*self.args)
MyThread.cnt -= 1
print('MyThread.cnt', MyThread.cnt)
@staticmethod
def myfunc(x):
for index in range(x):
print(threading.current_thread().getName(), index)
return x + 1
mt1 = MyThread(target=MyThread.myfunc, args=(5,))
mt2 = MyThread(target=MyThread.myfunc, args=(7,))
mt1.start()
mt2.start()
mt1.join()
mt2.join()
print(mt1.result, mt2.result)
'''
关于主线程结束时子线程是否会强制结束:
a线程创建b线程,如果a线程不是守护线程,那么实际上a和b两个线程没有必然联系。
b线程未结束,a线程该结束的时候还是会结束,除非a线程是守护线程,是的话会自动join。
main线程并不是守护线程,是由虚拟机创建的,也不能设置成守护线程。
而join是让a线程阻塞等b线程跑完为止,未必是需要的。
补充一点:
python中守护进程也称为后台进程:当程序中主线程及所有非守护线程执行结束时,
守护线程(例如一直死循环输出hello)也会随之消亡,程序将结束运行。
'''
# 话说,在java中应该使用接口
左斜线、正斜线、左斜杠、正斜杠 /
右斜线、反斜线、右斜杠、反斜杠
# cjgang.py
import os
# win10下
# 假设当前py文件同目录下有一个test文件夹,test下有一个logs文件夹,我要创建一个cj文件夹
os.system("mkdir testlogscj1") # 这个是可以的,因为l与c都不是转义符
# 假设当前py文件同目录下有一个test文件夹,test下有一个logs文件夹,我要创建一个nj文件夹
# os.system("mkdir testlogsnj0") # 这个是不行的
os.system("mkdir test\logs\nj1") # 这个是可以的
os.system(r"mkdir testlogsnj2") # 这个也是可以的,r就表示无转义符
# linux下
# 假设当前py文件同目录下有一个test文件夹,test下有一个logs文件夹,我要创建一个nj文件夹
os.system("mkdir test/logs/nj3") # 这个是可以的,因为没有就没有转义符
# 特别说明
# 其实上面的写法不太好,表示目录时应在路径末尾加斜框/或反斜杠,即:
os.system("mkdir test\logs\nj4\")
os.system("mkdir test/logs/nj5/")
# 综上
# 在win执行本程序,会生成cj1,nj1,nj2,nj4
# 在linux执行本程序,会生成nj3,nj5
'''
补充:关于网址中末层的/
http://www.abc.com/abc
http://www.abc.com/abc/
末尾带斜杠 / 的是目录/abc/,不带的是文件/abc,是两个不同的地址。
如访问/abc/,服务器会根据规则访问改目录下的默认首页文件,如/abc/index.html文件。
由于含index的文件可能有多个,如index.htm或index.jsp,服务器会根据规则选择优先级最高的显示。
如访问/abc,服务器则会寻找/abc文件,如果没有就把 abc 当做目录处理。
显然,是目录就该有末/,不是目录就该写http://www.abc.com/abc/index.html,才是比较好的习惯。
'''
SSH 传输
# ssh
# 第一部分:文件命令
import paramiko
t = paramiko.Transport(('100.115.157.101', 22))
t.connect(username='root', password='Huawei12#$')
chan = paramiko.SFTPClient.from_transport(t)
print(chan.put(localpath='config.json', remotepath='/root/CJ/444/config2.json')) # 上传文件
print(chan.stat(path='/root/CJ/444/config2.json')) # 查看文件属性
chan.get(remotepath='/root/CJ/444/config2.json', localpath='config3.json') # 下载文件
chan.mkdir(path='/root/CJ/444/666/', mode=paramiko.common.o777) # 建立目录
print(chan.listdir(path='/root/CJ/444/')) # 查看目录
print(chan.listdir_attr(path='/root/CJ/444/')) # 查看目录下文件以及子目录的详细信息,可能会报异常
chan.rmdir(path='/root/CJ/444/666/') # 删除目录
chan.remove(path='/root/CJ/444/config2.json') # 删除文件
chan.close() # 关闭通道
t.close()
# 第二部分:控制命令第一种写法(SSHClient)
import paramiko
t = paramiko.Transport(('100.115.157.101', 22))
t.connect(username='root', password='Huawei12#$')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
ssh._transport = t
stdin, stdout, stderr = ssh.exec_command('pwdnpwdn')
print(stdout.read()) # 注意read完缓冲区就会清空
ssh.close()
t.close()
# 第三部分:控制命令第二种写法(open_session)
import paramiko
t = paramiko.Transport(('100.115.157.101', 22))
t.connect(username='root', password='Huawei12#$')
chan = t.open_session()
chan.settimeout(15)
chan.invoke_shell()
chan.send(b'mkdir /root/CJ/444/555n')
chan.send(b'cd /root/CJ/444/nmkdir 666n')
chan.close()
t.close()
'''
个人感觉:用SSHClient可以解决一切问题,优先使用
还有就是,linux下删除直接用rm -rf即可,无论文件还是文件夹,无论文件夹是否为空,皆可用
'''
关于换行
经测试,win与linux都是n即可,例如下面:
补充说明一下:我是用notepad++打开的,以无bom的utf-8保存,如果是用记事本保存带bom的话要用utf-8-sig:
补充:win记事本默认ANSI格式,即GBK国标,没有中文时与无bom的utf-8相同



