Mô Hình Phi Chặn Đơn Tiến Trình
#coding=utf-8
from socket import *
import time
danh_sach_ket_noi = []
def main():
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server_socket.bind(('', 8080))
server_socket.listen(128)
server_socket.setblocking(False)
while True:
try:
client_socket, client_addr = server_socket.accept()
print(f"Kết nối mới: {client_addr}")
client_socket.setblocking(False)
danh_sach_ket_noi.append((client_socket, client_addr))
except BlockingIOError:
pass
for sock, addr in danh_sach_ket_noi[:]:
try:
du_lieu = sock.recv(1024)
if du_lieu:
print(f'Nhận từ {addr}: {du_lieu.decode()}')
else:
sock.close()
danh_sach_ket_noi.remove((sock, addr))
except BlockingIOError:
continue
if __name__ == '__main__':
main()
Máy Chủ Web Phi Chặn
import socket
import re
class WebServer:
def __init__(self, port, thu_muc_goc):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind(("", port))
self.server_socket.listen(128)
self.server_socket.setblocking(False)
self.danh_sach_client = []
self.thu_muc_goc = thu_muc_goc
def xu_ly_yeu_cau(self, request, client_socket):
if not request: return
ten_file = re.search(r"GET\s+(.*?)\s+HTTP", request)
ten_file = ten_file.group(1) if ten_file else "/index.html"
try:
with open(self.thu_muc_goc + ten_file, "rb") as f:
noi_dung = f.read()
header = (
"HTTP/1.1 200 OK\r\n"
f"Content-Length: {len(noi_dung)}\r\n\r\n"
).encode()
client_socket.send(header + noi_dung)
except FileNotFoundError:
loi = "404 Không tìm thấy tài nguyên"
header = (
"HTTP/1.1 404 Not Found\r\n"
f"Content-Length: {len(loi)}\r\n\r\n"
).encode()
client_socket.send(header + loi.encode())
def chay(self):
while True:
try:
client_socket, _ = self.server_socket.accept()
client_socket.setblocking(False)
self.danh_sach_client.append(client_socket)
except BlockingIOError:
pass
for sock in self.danh_sach_client[:]:
try:
du_lieu = sock.recv(1024).decode()
if du_lieu:
self.xu_ly_yeu_cau(du_lieu, sock)
else:
sock.close()
self.danh_sach_client.remove(sock)
except BlockingIOError:
continue
Mô Hình Epoll
import socket
import select
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("", 8888))
server.listen(10)
server.setblocking(False)
epoll_ctrl = select.epoll()
epoll_ctrl.register(server.fileno(), select.EPOLLIN)
ket_noi = {}
while True:
su_kien = epoll_ctrl.poll()
for fd, event in su_kien:
if fd == server.fileno():
client, addr = server.accept()
client.setblocking(False)
epoll_ctrl.register(client.fileno(), select.EPOLLIN)
ket_noi[client.fileno()] = client
elif event & select.EPOLLIN:
du_lieu = ket_noi[fd].recv(1024)
if du_lieu:
print(f"Nhận: {du_lieu.decode()}")
else:
epoll_ctrl.unregister(fd)
ket_noi[fd].close()
del ket_noi[fd]
Máy Chủ Web Sử Dụng Epoll
import socket
import select
import re
class WebServerEpoll:
def __init__(self, port, thu_muc_goc):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server.bind(("", port))
self.server.listen(128)
self.thu_muc_goc = thu_muc_goc
self.epoll = select.epoll()
self.epoll.register(self.server.fileno(), select.EPOLLIN)
self.socket_map = {}
def xu_ly_yeu_cau(self, request, client_socket):
# Logic xử lý tương tự phiên bản WSGIServer
pass
def chay(self):
while True:
events = self.epoll.poll()
for fd, event in events:
if fd == self.server.fileno():
client, _ = self.server.accept()
self.epoll.register(client.fileno(), select.EPOLLIN)
self.socket_map[client.fileno()] = client
elif event & select.EPOLLIN:
du_lieu = self.socket_map[fd].recv(1024)
if du_lieu:
self.xu_ly_yeu_cau(du_lieu.decode(), self.socket_map[fd])
else:
self.epoll.unregister(fd)
self.socket_map[fd].close()
del self.socket_map[fd]
Máy Chủ Web Sử Dụng Gevent
from gevent import monkey
import gevent
import socket
import re
monkey.patch_all()
class GeventWebServer:
def __init__(self, port, thu_muc_goc):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server.bind(("", port))
self.server.listen(128)
self.thu_muc_goc = thu_muc_goc
def xu_ly_client(self, client_socket):
while True:
du_lieu = client_socket.recv(1024).decode()
if not du_lieu: break
# Logic xử lý request tương tự
client_socket.send(b"HTTP/1.1 200 OK\r\n\r\nHello")
def chay(self):
while True:
client, _ = self.server.accept()
gevent.spawn(self.xu_ly_client, client)
Vấn Đề C10K
Tham khảo tài liệu về giới hạn kết nối đồng thời:
- http://www.52im.net/thread-561-1-1.html
- http://www.52im.net/thread-566-1-1.html