标签:
tcp/ip协议是主机接入互联网以及接入互联网的两台主机通信的标准。
数据帧 |-- 包头 | |--源地址 | |--目标地址 | |--数据类型 | |-- 数据
# 依照上socket流程图,实现一个功能,客户端输入什么,就把输入的转为大写 # soceet server import socket ip_port=(‘127.0.0.1‘,9999) # 封装协议(对象) s = socket.socket() # 绑定ip,端口 s.bind(ip_port) # 启动监听 s.listen(5) # 挂起连接数, 允许最多处理5个请求 while True: # 等待连接 conn, addr = s.accept() # accept方法等待客户端连接,直到有客户端连接后,会返回连接线(conn)、连接地址(addr) while True: # 至此,当客户端连接时,conn即为连接客户端的连接线 # 所以,当客户端主动断开连接时,conn就不存在了,也会抛出异常 # 在这里定义一个异常跟踪 try: # 接收消息 recv_data=conn.recv(1024) # 接收conn连接线路,并指定缓存该线路的1024 print(‘接收消息类型:%s‘ % type(recv_data)) # 发送消息 send_data=recv_data.upper() # 将接收消息转换为大写 print("发送消息内容:%s" % send_data) conn.send(send_data) # 使用conn线路,发送消息 except Exception: # 如果客户端主动断开,则server退出该循环等待下一条连接 break # 结束进程 conn.close() # 中断线路
# socket client import socket ip_port=(‘127.0.0.1‘,9999) # 封装协议(对象) s = socket.socket() # 向服务端建立连接 s.connect(ip_port) while True: # 发送消息 send_data=input(‘>>: ‘).strip() if len(send_data) == 0:continue # 如果发送消息为空,不去执行以下发送 s.send(bytes(send_data,encoding=‘utf8‘)) if send_data == ‘exit‘: break # 如果输入exit,则退出 # 接收消息 recv_data = s.recv(1024) # print(str(recv_data,encoding=‘utf8‘)) # 结束连接 s.close()
到目前为止,实现了以下功能:
1. client请求数据,server返回处理完数据
2. client断开,server不受影响
# socket server import socket import subprocess ip_port=(‘127.0.0.1‘,9999) # 封装协议(对象) s = socket.socket() # 绑定ip,端口 s.bind(ip_port) # 启动监听 s.listen(5) # 挂起连接数, 允许最多处理5个请求 while True: # 等待连接 conn, addr = s.accept() # accept方法等待客户端连接,直到有客户端连接后,会返回连接线(conn)、连接地址(addr) while True: # 至此,当客户端连接时,conn即为连接客户端的连接线 # 所以,当客户端主动断开连接时,conn就不存在了,也会抛出异常 # 在这里定义一个异常跟踪 try: # 接收消息 recv_data=conn.recv(1024) # 接收conn连接线路,并指定缓存该线路的1024 print(‘接收消息类型:%s‘ % type(recv_data)) # 发送消息 # 将接收的字节转换为str,传入subprocess.popen执行该命令,并定义stdout p=subprocess.Popen(str(recv_data,encoding=‘utf8‘),shell=True,stdout=subprocess.PIPE) # 读取stdout,res目前为gbk编码的bytes格式 res = p.stdout.read() if len(res) == 0: send_data=‘cmd err‘ else: # 将res(gbk编码的bytes格式) 按照gbk解码为字符串 send_data=str(res,encoding=‘gbk‘) # 将字符串(gbk格式)按照utf8编码转为bytes,发送给客户端 conn.send(bytes(send_data,encoding=‘utf8‘)) except Exception: # 如果客户端主动断开,则server正常退出 break # 结束进程 conn.close() # 中断线路
# socket client # client无改变 import socket ip_port=(‘127.0.0.1‘,9999) # 封装协议(对象) s = socket.socket() # 向服务端建立连接 s.connect(ip_port) while True: # 发送消息 send_data=input(‘>>: ‘).strip() if len(send_data) == 0:continue # 如果发送消息为空,不去执行以下发送 s.send(bytes(send_data,encoding=‘utf8‘)) if send_data == ‘exit‘: break # 如果输入exit,则退出 # 接收消息 recv_data = s.recv(1024) # print(str(recv_data,encoding=‘utf8‘)) # 结束连接 s.close()
# socket server # 粘包问题解决,就是在真正接收文件时,客户端与服务端确认文件大小, # 这样确定好大小后,只传输这么多大小的文件,即解决了粘包问题 import socket import subprocess ip_port=(‘127.0.0.1‘,9999) # 封装协议(对象) s = socket.socket() # 绑定ip,端口 s.bind(ip_port) # 启动监听 s.listen(5) # 挂起连接数, 允许最多处理5个请求 while True: # 等待连接 conn, addr = s.accept() # accept方法等待客户端连接,直到有客户端连接后,会返回连接线(conn)、连接地址(addr) while True: # 至此,当客户端连接时,conn即为连接客户端的连接线 # 所以,当客户端主动断开连接时,conn就不存在了,也会抛出异常 # 在这里定义一个异常跟踪 try: # 接收消息 recv_data=conn.recv(1024) # 接收conn连接线路,并指定缓存该线路的1024 print(‘接收消息类型:%s‘ % type(recv_data)) # 发送消息 # 将接收的字节转换为str,传入subprocess.popen执行该命令,并定义stdout p=subprocess.Popen(str(recv_data,encoding=‘utf8‘),shell=True,stdout=subprocess.PIPE) # 读取stdout,res目前为gbk编码的bytes格式 res = p.stdout.read() if len(res) == 0: send_data=‘cmd err‘ else: # 将res(gbk编码的bytes格式) 按照gbk解码为字符串 send_data=str(res,encoding=‘gbk‘) # 将字符串按utf8编码转换为bytes send_data = bytes(send_data, encoding=‘utf8‘) # 发送真正客户端数据之前,告诉客户端我发送的数据的字节长度, # 让客户端知道接收到哪里结束 read_tag = ‘Ready|%s‘ % len(send_data) # 取出数据长度 conn.send(bytes(read_tag,encoding=‘utf8‘)) # 将取出长度发给客户端 feedback = conn.recv(1024) # 客户端接收长度后,确认返回值 feedback=str(feedback,encoding=‘utf8‘) # 将客户端返回的确认值,转为str # 发送真正客户端请求数据 if feedback.startswith(‘Start‘): # 如果返回确认,则开始发送客户端所需要的数据 conn.send(send_data) # 将字符串(gbk格式)按照utf8编码转为bytes,发送给客户端 except Exception: # 如果客户端主动断开,则server正常退出 break # 结束进程 conn.close() # 中断线路
# socket client # 同server import socket ip_port=(‘127.0.0.1‘,9999) # 封装协议(对象) s = socket.socket() # 向服务端建立连接 s.connect(ip_port) while True: # 发送消息 send_data=input(‘>>: ‘).strip() if send_data == ‘exit‘: break # 如果输入exit,则退出 if len(send_data) == 0:continue # 如果发送消息为空,不去执行以下发送 s.send(bytes(send_data,encoding=‘utf8‘)) # 在接收server返回数据前,server返回本次传输数据的长度 ready_tag=s.recv(1024) # 使用1024字节记录本次数据长度 ready_tag=str(ready_tag,encoding=‘utf8‘) # 将bytes字符串 if ready_tag.startswith(‘Ready‘): # 如果server端返回Ready 即为准备好,可以发送数据包 msg_size=int(ready_tag.split(‘|‘)[1]) # 取出server要发送回的数据长度 start_tag=‘Start‘ s.send(bytes(start_tag,encoding=‘utf8‘)) # 返回给server 开始传输信息 # 接收消息 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()
# socket server
# 同样是一个转换大写的server
import socketserver class MyServer(socketserver.BaseRequestHandler): # 类继承socketserver.BaseRequestHandler def handle(self): self.request.sendall(bytes(‘欢迎致电10086,请输入1xxx,0转人工服务。‘,encoding=‘utf8‘)) while True: data = self.request.recv(1024) print("[%s] says:%s" % (self.client_address,data.decode())) self.request.sendall(data.upper()) if __name__ == ‘__main__‘: server = socketserver.ThreadingTCPServer((‘127.0.0.1‘,8009),MyServer) server.serve_forever() # 主要是继承并修改了socketserver.BaseRequestHandler类的handle方法 # 请直接阅读socketserver.BaseRequestHandler类,很简单的
# socket server # 模拟ssh import socketserver import subprocess class MyServer(socketserver.BaseRequestHandler): def handle(self): # print self.request,self.client_address,self.server self.request.sendall(bytes(‘欢迎致电 10086,请输入1xxx,0转人工服务.‘,encoding="utf-8")) while True: data = self.request.recv(1024) if len(data) == 0:break print("[%s] says:%s" % (self.client_address,data.decode() )) #self.request.sendall(data.upper()) cmd = subprocess.Popen(data.decode(),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) cmd_res =cmd.stdout.read() if not cmd_res: cmd_res = cmd.stderr.read() if len(cmd_res) == 0: #cmd has not output cmd_res = bytes("cmd has output",encoding="utf-8") self.request.send(cmd_res ) if __name__ == ‘__main__‘: server = socketserver.ThreadingTCPServer((‘0.0.0.0‘, 8009), MyServer) server.serve_forever()
# socket client import socket ip_port=(‘127.0.0.1‘,8009) # 封装协议(对象) s = socket.socket() # 向服务端建立连接 s.connect(ip_port) # 接收欢迎信息 welcome_msg = s.recv(1024) print("from server:",welcome_msg.decode()) while True: # 发送消息 send_data=input(‘>>: ‘).strip() if send_data == ‘exit‘: break # 如果输入exit,则退出 if len(send_data) == 0:continue # 如果发送消息为空,不去执行以下发送 s.send(bytes(send_data,encoding=‘utf8‘)) # 接收消息 recv_data=s.recv(1024) print(type(recv_data)) print(str(recv_data,encoding=‘gbk‘)) # 结束连接 s.close()
python学习笔记-Day9 (TCP/IP协议、socket)
标签:
原文地址:http://www.cnblogs.com/coolking/p/5648336.html