标签:
下面是一个socket编程示例,模拟ssh远程执行命令
socket建立连接的过程,模拟成打电话过程。
socket_server.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket import subprocess #导入执行命令模块 #定义"电话卡" ip_port=(‘127.0.0.1‘,9998) #定义元组 #"买手机" s=socket.socket() #绑定协议,生成套接字 #"将卡和手机绑定" s.bind(ip_port) #绑定ip+协议+端口:用来唯一标识一个进程,ip_port必须是元组格式 #"开机" s.listen(5) #定义最大可以挂起连接数 #等待电话 while True: #用来重复接收新的连接 conn,addr=s.accept() #接收客户端连接请求,返回conn(相当于一个特定连接),addr是客户端ip+port #收消息 while True: #用来基于一个连接重复收发消息 #捕捉客户端异常关闭(ctrl+c) #如果客户端异常关闭(没有执行close()),导致连接异常,服务端也会异常 try: recv_data=conn.recv(1024) #收消息,收到后阻塞,接收大小介于1024和8192之间 #print(len(recv_data)) #客户端如果正常退出(执行了close()),服务端recv函数将收到空消息,这时server端也退出 if len(recv_data) == 0: print("客户端正常退出") break p=subprocess.Popen(str(recv_data,encoding=‘utf8‘),shell=True,stdout=subprocess.PIPE) #执行系统命令 res=p.stdout.read() #获取标准输出 #如果执行命令错误,标准输出为空,必须判断标准输出是否为空,如果为空send_data就为‘cmd err‘,不然会导致客户端recv()阻塞 if len(res) == 0: send_data=‘cmd err‘ else: #windows平台命令的标准输出是gbk编码,需要转换,先转换成字符串(因为各种编码中字符串是一样的) send_data=str(res,encoding=‘gbk‘) #再转换成utf8,注意python3中需要转换成字节才能发送,python2中能直接发送字符串 send_data=bytes(send_data,encoding=‘utf8‘) #解决粘包问题 ready_tag=‘Ready|%s‘ %len(send_data) conn.send(bytes(ready_tag,encoding=‘utf8‘)) #告诉client端数据长度 feedback=conn.recv(1024) #接收确认信息 feedback=str(feedback,encoding=‘utf8‘) #接收的也是字节,需要转换成字符串 if feedback.startswith(‘Start‘): #如果确认信息是以"Start"开头 conn.send(send_data) #则发送命令的执行结果 except Exception: print("客户端异常退出") break #"挂电话" conn.close()
socket_client.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port=(‘127.0.0.1‘,9998) #"买手机" s=socket.socket() #"拨号" s.connect(ip_port) #连接服务端,如果服务端已经存在一个好的连接,那么挂起 while True: #基于connect建立的连接来循环发送消息 send_data=input(">>: ").strip() if send_data == ‘exit‘:break if len(send_data) == 0:continue s.send(bytes(send_data,encoding=‘utf8‘)) #解决粘包问题 ready_tag=s.recv(1024) #收取带数据长度的字节:Ready|9998 ready_tag=str(ready_tag,encoding=‘utf8‘) if ready_tag.startswith(‘Ready‘): #Ready|9998 msg_size=int(ready_tag.split(‘|‘)[-1]) #获取待接收数据长度 start_tag=‘Start‘ s.send(bytes(start_tag,encoding=‘utf8‘)) #发送确认信息"Start" #基于已经收到的待接收数据长度,循环接收数据 recv_size=0 recv_msg=b‘‘ #表示空字节 while recv_size < msg_size: recv_data=s.recv(1024) recv_msg+=recv_data recv_size+=len(recv_data) print(‘MSG SIZE %s RECE SIZE %s‘ %(msg_size,recv_size)) print(str(recv_msg,encoding=‘utf8‘)) #挂电话 s.close()
标签:
原文地址:http://www.cnblogs.com/zhoufeng1989/p/5650581.html