python-40-初识socket与struct
前言
网络中进程间如何通信?我怎么找到某个电脑上的某个程序进行通信呢?那么利用三元组【ip地址,协议,端口】可以进行网络间通信。
因此,Python中的socket模块便可以使其进行通信!但是通信过程中会出现黏包,Python中可以使用struct模块进行解决。
一、socket 模块
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端。
两个py文件之间进行通信实例:
①基于TCP协议的socket
server:服务端
import socket sk=socket.socket() sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('12.0.0.1',8080)) # 绑定服务端的:IP+端口 sk.listen() # 监听连接 conn, addr = sk.accept() # 接收连接 三次握手conn lis=list(addr) print('IP:%s 端口:%s 已请求连接!'%(lis[0],lis[1])) while 1: res=conn.recv(1024).decode('utf-8') # 接收信息 print(res) if res=='886':break ret=input('美女>>>') if ret=='886': conn.send(bytes(ret.encode('utf-8'))) # 发送信息 conn.send(bytes(ret.encode('utf-8'))) # 发送信息 conn.close() # 关闭客户端套接字 sk.close() #关闭服务器套接字
②client:客户端
import socket sk=socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8080)) # 尝试连接服务端 while 1: ret=input('帅哥>>>') if ret=='886': sk.send(bytes(ret.encode('utf-8'))) break sk.send(bytes(ret.encode('utf-8'))) # 发送信息 msg=sk.recv(1024).decode('utf-8') # 接收信息 print(msg) if msg=='886':break sk.close() # 关闭客户套接字
2、基于UDP协议的socket
udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接。
①server:服务端
# 2、基于UDP协议的socket # udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接 import socket udp_sk = socket.socket(type=socket.SOCK_DGRAM) # 创建一个服务器的套接字 udp_sk.bind(('127.0.0.1',8080)) # 绑定服务器套接字 msg,addr = udp_sk.recvfrom(1024) print(msg) udp_sk.sendto(b'udp_server',addr) # 对话(接收与发送) udp_sk.close() # 关闭服务器套接
②client:客户端
import socket ip_port=('127.0.0.1',8080) udp_sk=socket.socket(type=socket.SOCK_DGRAM) udp_sk.sendto(b'udp_client',ip_port) back_msg,addr=udp_sk.recvfrom(1024) print(back_msg.decode('utf-8'),addr)
3、长链接
①长链接:因同一时间只能一个程序链接,所以多个只会连接一个。
# 3、长链接 # 因同一时间只能一个程序链接,所以多个只会连接一个 import socket sk=socket.socket() sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('192.168.1.124',8080)) # 绑定服务端的:IP+端口 sk.listen() # 监听连接 while 1: conn, addr = sk.accept() # 接收连接 三次握手conn lis = list(addr) print('IP:%s 端口:%s 已请求连接!' % (lis[0], lis[1])) while 1: res = conn.recv(1024).decode('utf-8') # 接收信息 print(res) if res=='886':break ret=input('美女>>>') if ret=='886': conn.send(bytes(ret.encode('utf-8'))) # 发送信息 conn.send(bytes(ret.encode('utf-8'))) # 发送信息 conn.close() # 关闭客户端套接字
二、struct 模块
基本思路:
- 客户端传输的内容,len长度
- 将长度经过struct成为4位字节码
- 服务端解4位字节码,就知道了文件的大小
- 便开始传输
1、远程Windows cmd命令实例:
①server:服务端
import socket,struct sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen() conn,addr=sk.accept() while 1: cmd=input('请输入命令:') if cmd=='q': conn.send(b'q') break conn.send(cmd.encode('gbk')) # win系统gbk编码 num=conn.recv(4) num=struct.unpack('i',num)[0] # 将4个字节解码转为原来的大小 print(num) res=conn.recv(int(num)).decode('gbk') print(res) conn.close() sk.close()
②client:客户端
import socket,subprocess,struct sk=socket.socket() sk.connect(('127.0.0.1',8888)) while 1: cmd=sk.recv(1024).decode('gbk') if cmd=='q': break res=subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_out=res.stdout.read() std_err=res.stderr.read() len_num=len(std_out)+len(std_err) # 长度 num_by=struct.pack('i',len_num) # struct处理后变为4个字节 sk.send(num_by) # 先发送处理后的长度,让对方解字节 sk.send(std_out) sk.send(std_err) sk.close()
欢迎来大家QQ交流群一起学习:482713805