1、环境
python3 、 ubuntu系统(windows系统下没有epoll库,也不支持epoll)
2、思路
1、创建监听套接字,
2、绑定本地IP和port信息,本地信息使用元组格式
3、使用listen改变监听状态,设置监听容量
4、创建epoll对象,将监听套接字放入epoll中。
5、创建一个空字典放epoll返回的信息
6、循环取epoll返回的信息
7、对返回的信息做不同的处理
3、epoll的简单用法请参考:python 网络编程之epoll使用_Dream home-优快云博客
上代码:
import socket
from socket import *
import re,select
def client_sever(new_socket,request):
# 使用正则表达式匹配客户端发送的信息,获得服务端需要的信息,本次匹配资源地址
g=re.match(r'[^/]*/+([^ ]*)\s+',request)
file_name=g.group(1)
# 根据匹配结果,在本地进行操作
# 打开本地资源,读取本地数据作为响应体
try:
with open(file_name,'rb') as f:
response_body=f.read()
except:
response_body = '<h1>hello world!</h1>'.encode('utf-8')
finally:
response_header = 'HTTP/1.1\r\n'
response_header += '\r\n'
print(file_name)
# 组装本地数据a
response = response_header.encode('utf-8') + response_body
# 8、发送匹配后的本地资源给客户端
new_socket.send(response)
# 9、关闭客户端套接字,结束服务,等待下一个客户端链接。
new_socket.close()
def main():
# 1、创建监听套接字
server_socket=socket(AF_INET,SOCK_STREAM)
# 关闭socket ,端口立即释放
server_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
#server_socket.setblocking(False)
# 2、绑定本地IP和port信息,本地信息使用元组格式
server_socket.bind(('127.0.0.1',8080))
# 3、使用listen改变监听状态,设置监听容量
server_socket.listen(128)
# 4、创建epoll
epl=select.epoll()
# 5、将监听套接字放入epoll中,第一个参数为文件描述符,EPOLLIN 表示对应的文件描述符可以读
epl.register(server_socket.fileno(),select.EPOLLIN)
# 6、创建一个空字典放epoll返回的信息
fd_event_dict = dict()
fd_event_dict[server_socket.fileno()] = server_socket
while True:
# 默认为阻塞状态,直到os检测到epoll中数据发生修改,返回事件
events = epl.poll()
# 循环取epoll返回的列表
for fd ,event in events:
# 返回的文件描述服和监听套接字的文件描述符相等
if fd == server_socket.fileno():
# 接收服务端链接,创建为客户端服务的客户端套接字
new_socket, client_addr = server_socket.accept()
# 将服务客户端的套接字加入epoll中
epl.register(new_socket.fileno(),select.EPOLLIN)
fd_event_dict[new_socket.fileno()] = new_socket
elif event == select.EPOLLIN: # 可读事件
print('接收信息')
new_socket = fd_event_dict[fd]
# 获取服务端发送的信息,并设置接收数据字节大小
request = new_socket.recv(1024).decode('utf-8')
if request:
client_sever(new_socket,request)
elif event == select.EPOLLHUP: #客户断开事件,即客户端调用close()方法
print('关闭客户端服务套接字')
# 关闭客户端服务套接字
fd_event_dict[fd].close()
epl.unregister(fd)
del fd_event_dict[fd]
if __name__ == '__main__':
main()