python_day9_socket
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python_day9_socket相关的知识,希望对你有一定的参考价值。
1、socket 套接字工作流程图
2、收发功能
3、不间断一发一收
4、多客户端连接
5、UDP:收发功能
6、UDP:实现时间功能
7、执行命令
socket 套接字工作流程图
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
AF_UNIX: 基于文件编程
基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
AF_INET: 基于网络编程 有AF_INET6 ipv6
CS架构
SOCK_STREAM: TCP协议 数据流式通信
SOCK_DGRAM: UDP协议 数据报式的套接字
## 收发功能
socket服务端 import socket cat=socket.socket(socket.AF_INET,socket.SOCK_STREAM) cat.bind(('192.168.0.12',9090)) cat.listen(4) conn,addr=cat.accept() msg=conn.recv(1024) conn.close() print('接收到的信息: %s'%msg) conn.send(msg.upper()) cat.close() socket客户端 import socket cat=socket.socket(socket.AF_INET,socket.SOCK_STREAM) cat.connect(('192.168.0.12',9090)) cat.send('xiong'.encode('utf-8')) data=cat.recv(1024) print('接收到的信息: %s'%data)
#服务端会主动断开 已经传输完客户端数据的连接,将状态改变为TIME_WAIT, 四次挥手之后确定数据已经完全传输完,直接断开并清理状态连接信息
# 收发都是在操作自己的缓存区
# recv 接收的字节, 由recv用户态的应用程序发起
# 回车: 当前 socket 内核态缓存没数据 对端内核态也就没法收到数据,自然也就卡死了
##不间断一发一收
socket服务端 import socket cat=socket.socket(socket.AF_INET,socket.SOCK_STREAM) cat.bind(('127.0.0.1',9009)) cat.listen(5) conn,addr=cat.accept() while True: msg=conn.recv(1024) #回车: 当前 socket 内核态缓存没数据 对端内核态也就没法收到数据,自然也就卡死了 print('接收到的信息: %s'%msg.decode('utf-8')) if msg == b'q' : break inp = input('输入一个值: ') conn.send(inp.encode('utf-8')) continue conn.close() cat.close() socket客户端 import socket cat=socket.socket(socket.AF_INET,socket.SOCK_STREAM) cat.connect(('127.0.0.1',9009)) while True: inp = input('输入一个值: ') if inp == 'q': cat.send(inp.encode('utf-8')) break cat.send(inp.encode('utf-8')) msg = cat.recv(1024) print('接收到的信息: %s' % msg.decode('utf-8')) continue cat.close()
## 多客户端连接
# 1、当客户端与服务端建立连接,每次最大客户端连接数由listen控制,我这里最大是5个连接
# 2、多个客户端与服务端建立连接,每次只能有一个客户端与服务端通信,其它队列都会保持在队列中
# 3、unix有些系统使用try except无法解决客户端conn连接突然中断, 可以使用 if not conn: break
socket服务端 import socket cat=socket.socket(socket.AF_INET,socket.SOCK_STREAM) cat.bind(('192.168.2.192',9009)) cat.listen(5) while True: # 客户端退出,如果队列中还有连接那么再重新建立连接 conn,addr=cat.accept() # 连接一次 while True: # 与单个用户建立连接 try: msg=conn.recv(1024) # 当客户端关掉连接,而服务端连接却没有中断,它就直接报错 ConnectionResetError: [WinError 10054] except Exception: break print('接收到的信息: %s'%msg.decode('utf-8')) if msg == b'q' : break conn.send(msg.upper()) conn.close() # 关闭连接 cat.close() # 关闭程序 socket客户端 import socket cat=socket.socket(socket.AF_INET,socket.SOCK_STREAM) cat.connect(('192.168.2.192',9009)) while True: inp = input('输入一个值: ') if inp == 'q': cat.send(inp.encode('utf-8')) break cat.send(inp.encode('utf-8')) msg = cat.recv(1024) print('接收到的信息: %s' % msg.decode('utf-8')) continue cat.close()
UDP:收发功能
1、udp不需要建立accept连接,因为无需三次握手建立一条固定的通道
2、多个客户端同时连接服务端,可同时收发信息
3、udp可以接受空 (直接回车)???
recv在自己这端的缓冲区为空时,阻塞
recvfrom在自己这端的缓冲区为空时,就收一个空
UDP_socket服务端 import socket ip_port=('127.0.0.1',9999) udp_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) udp_sock.bind(ip_port) while True: data,addr=udp_sock.recvfrom(1024) print(data) udp_sock.sendto(data,addr) UDP_socket客户端 import socket ip_port=('127.0.0.1',9999) udp_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: inp = input('>>: ') udp_sock.sendto(inp.encode('utf-8'),ip_port) data,addr=udp_sock.recvfrom(1024) print(data)
UDP:实现时间功能
# 1、实现时间功能
# 2、data传递进来是二进制的格式,在strftime之前需要先将格式转换回来
# 3、注意格式转换,发送都是encode,接受基本都是recvfrom
# udp_socket_server端 import socket import time ip_port=('127.0.0.1',9001) udp_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) udp_sock.bind(ip_port) while True: data,addr=udp_sock.recvfrom(1024) print(data) if not data: default_time='%Y-%m-%d %X' else: default_time=data.decode('utf-8') udp_back_time=time.strftime(default_time) udp_sock.sendto(udp_back_time.encode('utf-8'),addr) # udp_socket_client端 import socket udp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) ip_port=('127.0.0.1',9001) #TypeError: sendto() takes 2 or 3 arguments (1 given) 需要带地址 while True: inp=input('>>: ') udp_client.sendto(inp.encode('utf-8'),ip_port) data,addr=udp_client.recvfrom(1024) print('现在时间是: %s'%data.decode('utf-8'))
# 1、先运行服务端 # 2、再运行客户端打印结果如下: 现在时间是: 18 >>: %Y 现在时间是: 2018 >>: 现在时间是: 2018-01-04 20:49:53 >>:
### 执行命令
# socket TCP服务端 import socket import subprocess ip_port=('127.0.0.1',9001) ip_connect=5 buff_size=1024 command=socket.socket(socket.AF_INET,socket.SOCK_STREAM) command.bind(ip_port) command.listen(ip_connect) while True: # 客户端断开之后保持重连 data,addr=command.accept() print('客户端连接信息: %s' %data) while True: try: # 接收客户端传递过来的值 cmd_value=data.recv(buff_size) except Exception: break # 执行传递过来的命令,将结果保存到管道对象中赋值给res res=subprocess.Popen(cmd_value.decode('utf-8'),shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) # 取出stderr的值,如果是空那么执行stdout,不为空说明报错了 err=res.stderr.read() if err: cmd_res=err else: cmd_res=res.stdout.read() if not cmd_res: # 判断如果是类似 cd .. 的命令,它到subprocess值为空 cmd_res='命令为空'.encode('gbk') data.send(cmd_res) continue data.close() command.close() # socket_客户端 import socket ip_port=('127.0.0.1',9001) ip_connect=5 buff_size=1024 command=socket.socket(socket.AF_INET,socket.SOCK_STREAM) command.connect(ip_port) while True: cmd_inp=input('请输入命令: ').strip() if not cmd_inp: command if cmd_inp == 'quit': break command.send(cmd_inp.encode('utf-8')) data=command.recv(buff_size) print(data.decode('gbk')) command.close() # 最后在客户端这边输入 dir就能看到结果了# 最后在客户端这边输入 dir就能看到结果了
以上是关于python_day9_socket的主要内容,如果未能解决你的问题,请参考以下文章