Python3基础之学习笔记(八)-socket网络编程-paramiko模块

1. socket网络编程

1.1 socket简介

Python 提供了两个级别访问的网络服务。:

  • 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
  • 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

1.2 socket简单通信实例

客户端

import socket
 
def main():
    client=socket.socket()#创建套接字,第二个参数type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
    client.connect(('127.0.0.1',7000))#连接服务端的ip和端口
    client.send('Hello World'.encode())#python3发送数据,只能发送字节数据
    data=client.recv(1024)#最多接收1024个字节,data是字节类型
    print('recv:',data.decode())#将字节类型变为str类型
    client.close()
 
 
if __name__ == "__main__":
    main()
'''
结果为:
recv: 你好世界!
'''

服务端

import socket
 
def main():
    server=socket.socket()#创建套接字
    server.bind(('127.0.0.1',7000))#绑定监听端口
    server.listen(5)#开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
    conn,addr=server.accept()#被动接受TCP客户端连接,(阻塞式)等待连接的到来,返回客户端连接和客户端地址
    print('客户端连接进来了,它的地址是:%s:%s'%addr)
    data=conn.recv(1024)#接收TCP数据,数据以字节形式返回,最多接收1024个字节
    print('recv:',data.decode())#将字节转化成str
    conn.send('你好世界!'.encode())#将字符串转换成bytes,python3只能发送字节类型
    server.close()
 
 
if __name__ == "__main__":
    main()
'''
结果:
客户端连接进来了,它的地址是:127.0.0.1:56580
recv: Hello World
'''

1.3 socket实现简单ssh

ssh服务端

import socket
import os
def main():
    server=socket.socket()
    server.bind(('127.0.0.1',7000))
    server.listen(5)
    while True:
        conn,addr=server.accept()
        print('客户端连接进来了,它的地址是:%s:%s'%addr)
        while True:
            data=conn.recv(1024).decode()
            if data=='exit':
                print('客户端已断开连接')
                conn.send(str(0).encode())
                break
            print('执行指令:',data)
            cmd_res=os.popen(data).read()#执行命令返回字符串
            if not cmd_res:
                cmd_res='错误的命令'
            conn.send(str(len(cmd_res.encode())).encode())#发送执行命令产生结果的数据大小
             code=conn.recv(1024).decode()#接收从客户端发来代码,如果为1,代表客户端接收成功,防止发送数据过快,数据粘在一起,产生粘包
            conn.send(cmd_res.encode())
    server.close()
 
if __name__ == "__main__":
    main()

ssh客户端

import socket
def main():
    client=socket.socket()
    client.connect(('127.0.0.1',7000))
    while True:
        cmd=input('>>:').strip()
        if len(cmd)==0:continue
        client.send(cmd.encode())
        cmd_res_size=int(client.recv(1024).decode())#接收命令结果的字节长度
        if cmd_res_size==0:break#返回0代表断开连接
        received_size=0
         client.send(str(1).encode())#防止粘包
        while received_size!=cmd_res_size:
            received_data=client.recv(1024)
            received_size+=len(received_data)
            print(received_data.decode())
    client.close()
 
if __name__ == "__main__":
    main()

1.4 socket文件传输

文件客户端

import socket
import hashlib
def main():
    client=socket.socket()
    client.connect(('127.0.0.1',7000))
    while True:
        cmd=input('>>:').strip()
        if len(cmd)==0:continue
        if  cmd.startswith('get'):
            client.send(cmd.encode())
            file_size=int(client.recv(1024).decode())#接收文件大小
            client.send('ready to recv file'.encode())#向服务端发送确认
            received_size=0
            f=open('a_'+cmd.split()[1],'wb')
            m=hashlib.md5()
            while received_size!=file_size:
                size=0
                #防止粘包
                if file_size-received_size>1024:
                    size=1024
                else:size=file_size-received_size
                received_data=client.recv(size)
                m.update(received_data)
                received_size+=len(received_data)
                f.write(received_data)
            else:
                received_md5=client.recv(1024).decode()
                if m.hexdigest()==received_md5:
                    print('file recv done')
        break
    client.close()
 
if __name__ == "__main__":
    main()

文件服务端

import socket
import os
import hashlib
def main():
    server=socket.socket()
    server.bind(('127.0.0.1',7000))
    server.listen(5)
    while True:
        conn,addr=server.accept()
        print('客户端连接进来了,它的地址是:%s:%s'%addr)
        while True:
            data=conn.recv(1024).decode()
            if not data:
                print('客户端已断开连接')
                break
            filename=data.split()[1]
            print('文件名是:',filename)
            if os.path.isfile(filename):
                f=open(filename,'rb')
                file_size=os.stat(filename).st_size#获取文件大小
                conn.send(str(file_size).encode())#发送文件大小
                acg=conn.recv(1024)#等待客户端确认
                m=hashlib.md5()
                for line in f:
                    m.update(line)#MD5加密,line是bytes类型
                    conn.send(line)
                conn.send(m.hexdigest().encode())
                f.close()
            break
        break
    server.close()
 
 
if __name__ == "__main__":
    main()

1.5 sockerserver

socketserver是标准库中一个高级别的模块,用于简化网络客户与服务器的实现。

socketserver服务端

import socketserver
class MyTcpHandler(socketserver.BaseRequestHandler):#每接收一个请求则实例化这个类
    def handle(self):#重写handle方法
        print('客户端的ip地址是:%s:%s' % self.client_address)
        while True:
            try:
                self.data=self.request.recv(1024).decode().strip()
                print('客户端发送的数据是:',self.data)
                self.request.send('Hello World!'.encode())
            except ConnectionResetError as e:
                print('客户端已断开连接')
                break
def main():
    HOST,PORT='127.0.0.1',7000
    server=socketserver.ThreadingTCPServer((HOST,PORT),MyTcpHandler)#支持多并发
    server.serve_forever()
if __name__ == "__main__":
    main()

socketserver客户端

import socket
def main():
    client=socket.socket()
    client.connect(('127.0.0.1',7000))
    while True:
        cmd=input('>>:').strip()
        client.send(cmd.encode())
        data=client.recv(1024).decode()
        print(data)
if __name__ == "__main__":
    main()

2. paramiko模块

paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。

2.1 基于用户名密码的连接

import paramiko
def main():
	#创建ssh对象
	ssh=paramiko.SSHClient()
	#允许连接不在know_hosts文件中的主机。
	ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
	#连接服务器
	ssh.connect(
		hostname='192.168.244.128',
		port=22,
		username='用户名',
		password='密码'
	)
	#执行命令
	stdin,stdout,stderr=ssh.exec_command('ifconfig')
	#获取命令结果
	result=stdout.read()
	print(result.decode())
if __name__ == "__main__":
	main()

2.2 基于用户名和密码的上传下载

import paramiko
def main(): 
	transport = paramiko.Transport(('hostname',22))
	transport.connect(username='用户名',password='密码')
	sftp = paramiko.SFTPClient.from_transport(transport)
	# 将1.txt上传至服务器 /tmp/1.txt
	sftp.put('1.txt', '/tmp/1.txt')
	# 将2.txt下载到本地
	sftp.get('2.txt', '/tmp/2.txt') 
	transport.close()
if __name__ == "__main__":
	main()

你可能感兴趣的:(Python)