socket
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
1.首先来看一下简易版的客户端与服务器的搭建
客户端
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘,9999) #测试地址与端口 sk = socket.socket() #生成句柄 sk.connect(ip_port) #连接服务器 sk.sendall(bytes(‘...connecting...‘, ‘utf8‘)) #python3中以字发送数据 server_reply = sk.recv(1024) #接收来自服务器的数据 print(str(server_reply, ‘utf8‘)) #输出时用字符串形式 sk.close()
服务器
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘, 9999) sk = socket.socket() #生成句柄 sk.bind(ip_port) #绑定ip地址和端口 sk.listen(5) #监听,5为最大连接个数 while True: print(‘...server waiting...‘) conn, addr = sk.accept() #阻塞待连,生成实例conn,并返回实例和地址 client_data = conn.recv(1024) #接收实例的数据,1024个字符 print(str(client_data, ‘utf8‘)) conn.sendall(bytes(‘...connect successfully...‘,‘utf8‘))#服务器发回的数据 conn.close()
2.改进:以上例子只能实现一次性通信,我们改进的动机是想要完成一个类似于QQ聊天的交互式通信
客户端
import socket ip_port = (‘127.0.0.1‘,9999) sk = socket.socket() sk.connect(ip_port) sk.sendall(bytes(‘请求通讯‘, ‘utf8‘)) server_reply = sk.recv(1024) print(str(server_reply, ‘utf8‘)) while True: #交互式通信 userInput = input(">>:").strip() sk.send(bytes(userInput, ‘utf8‘)) server_reply = sk.recv(1024) print(str(server_reply, ‘utf8‘)) sk.close()
服务器
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘, 9999) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: print(‘server waiting...‘) conn, addr = sk.accept() client_data = conn.recv(1024) print(str(client_data, ‘utf8‘)) conn.sendall(bytes(‘连接成功‘, ‘utf8‘)) while True: client_data = conn.recv(1024) print(str(client_data, ‘utf8‘)) server_response = input("\033[32;1m>>:\033[0m").strip() conn.send(bytes(server_response)) conn.close()
3.改进:实现服务器在多连接情况下异常处理
客户端
import socket ip_port = (‘127.0.0.1‘, 9999) sk = socket.socket() sk.connect(ip_port) sk.sendall(bytes(‘请求通讯‘, ‘utf8‘)) server_reply = sk.recv(1024) print(str(server_reply, ‘utf8‘)) while True: userInput = input(">>:").strip() sk.send(bytes(userInput, ‘utf8‘)) server_reply = sk.recv(1024) print(str(server_reply, ‘utf8‘)) sk.close()
服务器
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘, 9999) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: print(‘server waiting...‘) conn,addr = sk.accept() client_data = conn.recv(1024) print(str(client_data, ‘utf8‘)) conn.sendall(bytes(‘不要回答,不要回答,不要回答‘,‘utf8‘)) while True: try: client_data = conn.recv(1024) print(str(client_data,‘utf8‘)) except Exception: print("Connection break!!!") break conn.send(client_data) conn.close() # while True: Linux version # client_data = conn.recv(1024) # print("recv:",str(client_data,‘utf8‘)) # if not client_data:break # conn.send(client_data)
4.在Linux上实现SSH的通讯:解决大数据的传输
客户端:
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘,9999) sk = socket.socket() sk.connect(ip_port) while True: user_input = input("cmd>>:").strip() if len(user_input) == 0:continue if user_input == ‘q‘:break sk.send(bytes(user_input,‘utf8‘)) #ack_msg = b"CMD_RESULT_SIZE|%s" % len(cmd-result) server_ack_msg = sk.recv(100) cmd_res_msg = str(server_ack_msg).split("|") if cmd_res_msg[0] == "CMD_RESULT_SIZE": cmd_res_size = int(cmd_res_msg[1]) sk.send(b"CLIENT_READY_TO_RECV") res = ‘‘ rec_size = 0 while rec_size <= cmd_res_size: data = sk.recv(500) rec_size += len(data) #实际大小 res += str(data.decode()) else: print(str(res)) print("......recv done....") sk.close()
服务端:
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket import time import subprocess ip_port = (‘127.0.0.1‘, 9999) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: print(‘server waiting...‘) conn,addr = sk.accept() while True: client_data = conn.recv(1024) if not client_data:break print("recv:", str(client_data, ‘utf8‘)) cmd = str(client_data,"utf8").strip() cmd_call = subbprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE) cmd_result = cmd_call.stdout.read() if len(cmd_result) == 0: cmd_result = b"cmd execution has no output.." ack_msg = b"CMD_RESULT_SIZE|%s" % len(cmd_result) conn.send(ack_msg) conn.recv(10) #生成阻塞,分割两次发送,避免,两次分开的数据一起发出去了。 if client_ack.decode() == ‘CLENT_READY_TO_RECV‘: conn.send(cmd_result) #但这种方法,cpu浪费了大量的时间 conn.close()
时间: 2024-10-25 17:05:45