python学习socket库(套接字)
TCP:
使用默认的方式:
服务端:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 6969))
sock.listen(5)
while True:
conn, addr = sock.accept()
with conn:
print('Connected By:', addr)
while True:
try:
recv_data = conn.recv(1024)
if not recv_data:
break
print('accept mag:', recv_data.decode())
conn.sendall(recv_data)
except ConnectionResetError as e:
print('close using connection!')
break
conn.close()
sock.close()
服务端:
import socket
HOST = '192.168.41.192'
PORT = 6969
sock_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_client.connect((HOST, PORT))
while True:
msg = input('>>>>:').strip()
sock_client.sendall(msg.encode())
data = sock_client.recv(1024)
print('client accept msg:', data.decode())
默认的socket是阻塞的方式
使用非阻塞情况下:
import socket
# 同步非阻塞
HOST = ''
PORT = 50007
sock = socket.socket()
sock.setblocking(False) # 设置非阻塞 默认为阻塞TRUE
sock.bind((HOST, PORT))
sock.listen(5)
while True:
try:
conn, addr = sock.accept() # 没有连接会引发BlockingIOError
with conn:
print('Connected by:', addr)
except BlockingIOError:
pass
使用非阻塞实现并发:
import socket
# 使用同步非阻塞实现服务器并发(缺点:任意一个客服端关闭,服务端会随着客服端关闭)
HOST = ''
PORT = 50007
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.bind((HOST, PORT))
sock.listen(5)
client_list = []
while True:
# 接受数据
try:
conn, addr = sock.accept()
conn.setblocking(False) # 设置这个对等数列链接为非阻塞
client_list.append((conn, addr))
print('Connected by: {}'.format(addr))
except BlockingIOError:
pass
# 处理请求
for client, addr in client_list:
try:
recv_data = client.recv(1024)
if recv_data:
print('接受来自:{}>>>{}'.format(addr, recv_data.decode()))
client.sendall(recv_data)
else:
# 关闭链接
client_list.remove((client, addr)) # 从列表中删除
client.close()
print('断开链接:{}'.format(addr))
except BlockingIOError:
pass
为了提高效率,使用epoll实现并发服务器:
import socket
import selectors
HOST = '192.168.41.192'
PORT = 50007
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
def recv(soc):
try:
data = soc.recv(1024)
if data:
print("accept data:", data.decode())
soc.send(data)
else:
# 删除注册
epoll_selector.unregister(soc)
soc.close()
except ConnectionResetError as e:
print('close connection.')
epoll_selector.unregister(soc)
soc.close()
def accept(soc):
# 接受请求
conn, addr = soc.accept()
print("Connected by:", addr)
# 把对等链接注册到epoll监视器
epoll_selector.register(
conn,
selectors.EVENT_READ,
recv
)
# 创建一个epoll监视器
# epoll_selector = selectors.DefaultSelector() # 根据操作系统自己选择(这里是window)
epoll_selector = selectors.EpollSelector()
# 注册
epoll_selector.register(
sock,
selectors.EVENT_READ,
accept
)
# 循环监听
while True:
# events 是一个列表
events = epoll_selector.select()
# events 就是所有被触发 的事件
for key, mark in events:
sock = key.fileobj
callback = key.data
# 执行回调函数
callback(sock)
实现Linux定时执行脚本:
shell脚本代码:
#! /bin/bash
pid=$(ps -ef | grep "new_server.py" | grep -w "python3")
echo "pid=$pid" >> /home/app/a.log
if [ "x$pid" == "x" ]; then
python3 /home/app/new_server.py &
fi
需要在crontab -e打开文件
* * * * * sh /home/app/test.sh >/dev/null 2>&1