socket是一个模块,又称套接字,用来封装互联网协议(应用层如下的层)python
实现应用层如下的层的工做,提升开发效率shell
先导入socket模块,先启动服务端套接字,再启动客户端套接字json
# 服务端 import socket # 买手机 server = socket.socket() # 绑定手机号(IP,port) # IP单机模式是127.0.0.1,局域网内使用cmd中ipconfig查询IPV4 # port设置8000之后的数据 server.bind(('127.0.0.1', 9876)) # 设置半链接池 server.listen(4) # 可接收多个客户端数据链接,实现循环通讯 while True: # 接收客户端链接 conn, addr = server.accept() # 查看对方地址 print(addr) while True: # 捕获异常机制 try: # 接收客户端发来的数据,可一次接收1024bytes的数据 data = conn.recv(1024) if len(date) == 0: break if data.decode('utf-8') == 'q': break print(data.decode('utf-8')) # 向客户端发送消息 send_data = input('请输入向客户端发送的数据:') conn.send(send_data.encode('utf-8')) # 捕获异常,并打印出错误信息 except Exception as e: print(e) break # 挂电话 conn.close()
# 客户端 import socket # 买手机 client = socket.socket() # 创建链接(IP,port) client.connect(('127.0.0.1',9876)) while True: try: # 向对方发送数据 data = input('请输入向服务端发送的数据') client.send((data.encode('utf--8'))) # 接收对方发来的数据可设置一次接收的bytes数,并打印 res_data = client.recv(1024) if len(res_data) == 0: break if res_data.decode('utf-8') == 'q': break print(res_data.decode('utf-8')) # 捕获异常,并打印出异常 except Exception as e: print(e) break client.close()
没法确认对方发送过来数据大小并发
在发送数据间隔短而且数据量小的状况下,会将全部数据一次性发送socket
解决:须要确认对方发送的数据大小code
# 客户端 # 问题1 import socket client = socket.socket() client.connect(('127.0.0.1', 9876)) while True: try: cmd = input('请输入向服务端发送的命令:') client.send(cmd.encode('utf-8')) # 接收服务端返回的数据 # 因为不知道会返回多少个bytes因此有问题1 date = client.recv(11910) print(len(date)) print(date.decode('gbk')) except Exception as e: print(e) break client.close()
# 客户端 # 问题2 # 时间间隔短,并数据量小的状况下,会将全部的数据一次性发送,接收时不知道具体有几个 import socket client = socket.socket() client.connect(('127.0.0.1', 9876)) client.send(b'hello') client.send(b'hello') client.send(b'hello') client.send(b'hello') client.send(b'hello')
# 服务端 import socket import subprocess server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(4) while True: conn, addr = server.accept() print(addr) while True: try: # 接收客户端的数据,具体值不知道多大,全部有可能不能彻底接收,有可能浪费资源 cmd = conn.recv(12) if len(cmd) == 0: break cmd = cmd.decode('utf-8') if cmd == 'q': break # 调用subprocess链接终端,对终端进行操做,并获取正确和错误的结果 obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 拿到结果,并打印 result = obj.stdout.read() + obj.stderr.read() print(result.decode('gbk')) # 将结果返回给客户端 conn.send(result) except Exception as e: print(e) break conn.close()
使用struct模块server
struct 是一个python内置的模块,它能够将固定长度的数据,打包成固定格式的长度ip
模式:i:4,或其余模式utf-8
做用:将真实数据作成一个固定长度的报头,发送给服务端,服务端接收报头,而后进行解包,获取真实数据的长度,进行接收数据便可资源
import struct data = input('请输入传的数据').strip() data = data.encode('utf-8') # 制做报头,须要 i 的字符串和传入数据的长度 header = struct.pack('i',len(data)) print(header) print(len(header)) # 解包( i 的字符串和报头)获取真实长度,获得一个元组,拿到元组第一个数就是真实长度 res = struct.unpack('i', header)[0] print(res) # utf-8中一个中文是3个bytes,一个英文是1个bytes
客户端:
1.先制做报头,并发送
2.发送真实数据
服务端:
1.接收报头,而且解包获取真实数据长度
2.根据真实数据长度,接收真实数据
# 客户端 import socket import struct client = socket.socket() client.connect(('127.0.0.1', 9876)) while True: try: cmd = input('请输入向服务端发送的命令') cmd_bytes = cmd.encode('utf-8') # 作一个报头 header = struct.pack('i', len(cmd_bytes)) # 发送报头 client.send(header) # 发送真实数据 client.send(cmd_bytes) # 接受服务端返回的报头 reheader = client.recv(4) # 解包 data_len = struct.unpack('i', reheader)[0] result = client.recv(data_len) print(result.decode('gbk')) except Exception as e: print(e) break client.close()
# 服务端 import socket import subprocess import struct server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(5) while True: conn, addr = server.accept() while True: try: # 获取报头 header = conn.recv(4) # 获取真实数据长度 data_len = struct.unpack('i', header)[0] # 准备接受真实数据 cmd = conn.recv(data_len) cmd = cmd.decode('utf-8') if cmd == 'q': break if len(cmd) == 0: break obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = obj.stdout.read() + obj.stderr.read() print(len(result)) print(result.decode('gbk')) # 将结果返回给客户端 header = struct.pack('i', len(result)) conn.send(header) conn.send(result) except Exception as e: print(e) break conn.close()
# 客户端 import socket import struct import json client = socket.socket() client.connect(('127.0.0.1', 9876)) while True: # 假装电影数据 movie_name = input('请输入电影名称:') movie_len = 10000101 send_dic = { 'movie_name': movie_name, 'movie_len': movie_len } # 序列化 json_data = json.dumps(send_dic) # 制做报头 json_bytes = json_data.encode('utf-8') header = struct.pack('i', len(json_bytes)) # 发送报头 client.send(header) # 发送真实数据 client.send(json_bytes)
# 服务端 import socket import json import struct server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(5) while True: conn, addr = server.accept() print(addr) while True: try: # 接收报头 header = conn.recv(4) # 解包获取真实长度 json_len = struct.unpack('i', header)[0] # 接收真实长度 json_bytes_data = conn.recv(json_len) json_data = json_bytes_data.decode('utf-8') # 反序列化获得数据 back_dic = json.loads(json_data) print(back_dic) except Exception as e: print(e) break conn.close()