Chúng ta đã hoàn thành những kiến thức cơ bản về cách làm việc với socket và bây giờ chúng ta đã sẵn sàng thử thực sự xây dựng thứ gì đó với chúng, vì vậy, trong hướng dẫn về socket với Python này, chúng ta sẽ xây dựng một ứng dụng trò chuyện dựa trên bảng điều khiển
Để bắt đầu, chúng ta sẽ xây dựng
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]3. Các chức năng của máy chủ của chúng tôi sẽ là gì?
Đầu tiên, máy chủ cần chấp nhận các kết nối mới từ máy khách. Từ đây, chúng ta cần nghĩ ra một số cách để xác định người dùng duy nhất của mình. Chúng tôi có thể hiển thị người dùng theo địa chỉ IP, nhưng hầu hết mọi người có xu hướng nghĩ ra một số loại tên người dùng, vì vậy trước tiên máy chủ của chúng tôi sẽ cho phép khách hàng kết nối và chọn tên người dùng. Ngoài điều này, máy chủ sẽ thu thập các tin nhắn đến và sau đó phân phối chúng cho các máy khách được kết nối còn lại
Vì vậy, chúng tôi sẽ bắt đầu với việc nhập và một số giá trị bắt đầu
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 1234
Không có gì mới ở đây ngoại trừ việc nhập khẩu
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]4. Đây là gì? . Nó đặc biệt hữu ích trong trường hợp chúng tôi đang cố gắng giám sát đồng thời nhiều kết nối. Mặc dù bạn có thể sử dụng vòng lặp for để lặp qua tất cả các ổ cắm, nhưng sử dụng
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]4 sẽ hiệu quả hơn nhiều và sẽ mở rộng quy mô tốt hơn nhiều, chủ yếu là vì nó sẽ hoạt động trên lớp hệ điều hành của bạn, thay vì toàn bộ Python. Về cách sử dụng nó, chúng ta sẽ nói về nó nhiều hơn khi đến điểm đó
Ban đầu thiết lập ổ cắm của chúng tôi
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
Tiếp theo, chúng ta có thể thiết lập như sau để vượt qua "Địa chỉ đã được sử dụng" mà chúng ta thường gặp khi xây dựng chương trình của mình
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]
Điều này sửa đổi ổ cắm để cho phép chúng tôi sử dụng lại địa chỉ
Tiếp theo, chúng tôi liên kết và lắng nghe
server_socket.bind[[IP, PORT]] server_socket.listen[]
Tiếp theo, chúng tôi sẽ tạo một danh sách các ổ cắm cho
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]4 để theo dõi, cũng như bắt đầu lệnh
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]8 của chúng tôi
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 12340
Một số thông tin gỡ lỗi
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 12341
Bây giờ, công việc chính của máy chủ này là nhận tin nhắn, sau đó phân tán chúng đến các máy khách được kết nối. Để nhận tin nhắn, chúng ta sẽ tạo một chức năng
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 12342
Bước 1 để nhận tin nhắn là đọc tiêu đề
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 12343
Nếu khách hàng đóng kết nối một cách duyên dáng, thì một
server_socket.setsockopt[socket.SOL_SOCKET, socket.SO_REUSEADDR, 1]9 sẽ được cấp và sẽ không có tiêu đề. Chúng tôi có thể xử lý điều đó với
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 12345
Sau đó, chúng tôi có thể chuyển đổi tiêu đề của mình thành độ dài
import socket import select HEADER_LENGTH = 10 IP = "127.0.0.1" PORT = 12346
Cuối cùng, chúng ta có thể trả về một số dữ liệu có ý nghĩa
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]0
Mã đầy đủ ngay bây giờ
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]1
Bây giờ, những gì chúng tôi muốn làm là, trong một vòng lặp liên tục, nhận tin nhắn cho tất cả các ổ cắm máy khách của chúng tôi, sau đó gửi tất cả tin nhắn đến tất cả các ổ cắm máy khách. Để bắt đầu, chúng tôi sẽ sử dụng vòng lặp
server_socket.bind[[IP, PORT]] server_socket.listen[]0 và sau đó chúng tôi sẽ sử dụng
server_socket.bind[[IP, PORT]] server_socket.listen[]1
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]2
Điều này không hoàn toàn đơn giản, nhưng nó khá đơn giản. Chúng tôi hoàn toàn sử dụng
server_socket.bind[[IP, PORT]] server_socket.listen[]1 ở đây cho i/o cấp hệ điều hành đã nói ở trên cho các ổ cắm của chúng tôi. Hàm này lấy tham số là
server_socket.bind[[IP, PORT]] server_socket.listen[]3,
server_socket.bind[[IP, PORT]] server_socket.listen[]4 và
server_socket.bind[[IP, PORT]] server_socket.listen[]5. lần lượt là danh sách đọc, danh sách ghi và danh sách lỗi. Trả về của hàm này là 3 phần tử giống nhau trong đó trả về là "tập hợp con" của danh sách đầu vào trong đó tập hợp con là danh sách các ổ cắm đã sẵn sàng
Bây giờ, từ đây, chúng ta sẽ lặp lại danh sách
server_socket.bind[[IP, PORT]] server_socket.listen[]6. Đây là những ổ cắm có dữ liệu được đọc
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]3
Nếu ổ cắm được thông báo là ổ cắm máy chủ của chúng tôi, thì điều này có nghĩa là chúng tôi vừa có một kết nối mới mà chúng tôi muốn xử lý
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]4
Vì vậy, với
server_socket.bind[[IP, PORT]] server_socket.listen[]7, chúng tôi có được ổ cắm máy khách duy nhất đó và địa chỉ của họ. Sau đó, chúng tôi lưu trữ tên người dùng đã chọn của họ thành tên họ đã chọn [đây phải là thứ đầu tiên khách hàng sẽ gửi]. Nếu vì một lý do nào đó, điều đó không xảy ra [chẳng hạn như khách hàng đã đóng trước khi gửi tên], thì chúng tôi sẽ tiếp tục
Tiếp theo, chúng tôi muốn nối thêm
server_socket.bind[[IP, PORT]] server_socket.listen[]8 mới này vào
server_socket.bind[[IP, PORT]] server_socket.listen[]9 của chúng tôi
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]5
Sau này, chúng tôi muốn lưu tên người dùng của khách hàng này, chúng tôi sẽ lưu tên người dùng này làm giá trị cho khóa là đối tượng ổ cắm
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]6
Nếu ổ cắm được thông báo không phải là ổ cắm máy chủ, thì điều này có nghĩa là thay vào đó, chúng tôi có một thông báo để đọc
server_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]7
Trước khi chúng tôi cố gắng đọc tin nhắn, hãy đảm bảo rằng một tin nhắn tồn tại. Nếu khách hàng ngắt kết nối, thì thông báo sẽ trống