Gửi đối tượng qua ổ cắm Python

Ổ cắm mạng là điểm cuối của giao tiếp liên quá trình qua mạng máy tính. Thư viện chuẩn Python có một mô-đun có tên là

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7 cung cấp giao diện mạng internet cấp thấp. Giao diện này phổ biến trên các ngôn ngữ lập trình khác nhau vì nó sử dụng các lệnh gọi hệ thống cấp hệ điều hành

Để tạo socket, có một hàm tên là

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7. Nó chấp nhận các đối số
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
9,
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
0 và
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1 (xem tài liệu để biết chi tiết). Để tạo ổ cắm TCP, bạn nên sử dụng
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
0 hoặc
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
1 cho
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
9 và
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
3 cho
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
4Đây là một ví dụ về ổ cắm Python

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Nó trả về một đối tượng ổ cắm có các phương thức chính sau

  • import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('localhost', 50000))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall(data)
    conn.close()
    5
  • import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('localhost', 50000))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall(data)
    conn.close()
    6
  • import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('localhost', 50000))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall(data)
    conn.close()
    7
  • import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('localhost', 50000))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall(data)
    conn.close()
    8
  • import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('localhost', 50000))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall(data)
    conn.close()
    9
  • import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('localhost', 50000))
    s.listen(1)
    conn, addr = s.accept()
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall(data)
    conn.close()
    00

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
5,
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
6 và
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7 dành riêng cho ổ cắm máy chủ.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
8 dành riêng cho ổ cắm máy khách.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
9 và
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
00 là chung cho cả hai loại. Đây là một ví dụ về máy chủ Echo từ tài liệu

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()

Ở đây chúng tôi tạo một ổ cắm máy chủ, liên kết nó với một cổng localhost và 50000 và bắt đầu lắng nghe các kết nối đến. Để chấp nhận kết nối đến, chúng tôi gọi phương thức

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7 sẽ chặn cho đến khi khách hàng mới kết nối. Khi điều này xảy ra, nó sẽ tạo một ổ cắm mới và trả về cùng với địa chỉ của máy khách. Sau đó, trong một chu kỳ vô hạn, nó đọc dữ liệu từ ổ cắm theo lô 1024 byte bằng phương thức
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
00 cho đến khi nó trả về một chuỗi rỗng. Sau đó, nó sẽ gửi lại tất cả dữ liệu đến bằng một phương thức thuận tiện
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
09 mà bên trong liên tục gọi
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
9. Và sau đó, nó chỉ cần đóng kết nối của máy khách. Ví dụ này chỉ có thể phục vụ một kết nối đến vì nó không gọi
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7 trong một chu kỳ

Mã phía máy khách trông đơn giản hơn

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
0

Ở đây thay vì

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
5 và
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
6, nó chỉ gọi
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
8 và ngay lập tức gửi dữ liệu đến máy chủ. Sau đó, nó nhận lại 1024 byte, đóng ổ cắm và in dữ liệu đã nhận

Tất cả các phương pháp ổ cắm đang chặn. Ví dụ, khi nó đọc hoặc ghi từ một ổ cắm, chương trình không thể làm gì khác. Một giải pháp khả thi là ủy quyền làm việc với khách hàng để tách các chủ đề. Tuy nhiên, việc tạo các luồng và chuyển ngữ cảnh giữa chúng không thực sự là một hoạt động rẻ tiền. Để giải quyết vấn đề này, có một cách gọi là cách làm việc không đồng bộ với socket. Ý tưởng chính là ủy thác việc duy trì trạng thái của ổ cắm cho một hệ điều hành và để nó thông báo cho chương trình khi có thứ gì đó cần đọc từ ổ cắm hoặc khi nó sẵn sàng để ghi.

Có rất nhiều giao diện cho các hệ điều hành khác nhau

  • thăm dò ý kiến, epoll (linux)
  • kqueue, kevent (BSD)
  • chọn (đa nền tảng)

Tất cả chúng đều giống nhau, vì vậy hãy tạo một máy chủ bằng Python chọn. Đây là một ví dụ về Python

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
75

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7

Như bạn có thể thấy, có nhiều mã hơn trong máy chủ Echo đang chặn. Điều đó chủ yếu là do chúng tôi phải duy trì một tập hợp hàng đợi cho các danh sách ổ cắm khác nhau, tôi. e. viết, đọc và một danh sách riêng cho các ổ cắm bị lỗi

Tạo ổ cắm máy chủ trông giống nhau ngoại trừ một dòng.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
76. Điều này được thực hiện để làm cho ổ cắm không bị chặn. Máy chủ này cao cấp hơn vì nó có thể phục vụ nhiều hơn một máy khách. Điểm chính là ở ổ cắm
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
77

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
1

Ở đây, chúng tôi gọi

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
78 để yêu cầu HĐH kiểm tra các ổ cắm đã cho xem chúng đã sẵn sàng để viết, đọc hay có một số ngoại lệ tương ứng. Đó là lý do tại sao nó vượt qua ba danh sách ổ cắm để chỉ định ổ cắm nào được cho là có thể ghi, có thể đọc và ổ cắm nào cần được kiểm tra lỗi. Cuộc gọi này sẽ chặn chương trình (trừ khi đối số hết thời gian chờ được thông qua) cho đến khi một số ổ cắm được thông qua sẵn sàng. Tại thời điểm này, cuộc gọi sẽ trả về ba danh sách có ổ cắm cho các hoạt động được chỉ định

Sau đó, nó tuần tự lặp lại các danh sách đó và nếu có ổ cắm trong đó, nó sẽ thực hiện các hoạt động tương ứng. Khi có ổ cắm máy chủ trong

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
79, điều đó có nghĩa là một máy khách mới đã đến. Do đó, nó gọi
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
7, thêm một ổ cắm được trả về vào
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
79 và thêm một
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 50000))
s.listen(1)
conn, addr = s.accept()
while 1:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()
12 cho các tin nhắn đến sẽ được gửi lại. Nếu có một ổ cắm khác trong đầu vào, thì một số tin nhắn đã đến và sẵn sàng để đọc để nó đọc chúng và đặt chúng vào hàng đợi tương ứng

Đối với các ổ cắm có thể ghi, nó sẽ nhận các tin nhắn đang chờ xử lý (nếu có) và ghi chúng vào ổ cắm. Nếu có bất kỳ lỗi nào trong ổ cắm, nó sẽ xóa ổ cắm khỏi danh sách

Đây là cách socket hoạt động ở mức thấp hơn. Tuy nhiên, trong hầu hết các trường hợp, không cần triển khai logic ở mức thấp như vậy. Bạn nên sử dụng một số trừu tượng cấp cao hơn như Twisted, Tornado hoặc ZeroMQ, tùy thuộc vào tình huống.

Chúng tôi hoan nghênh bạn xem trang nghiên cứu điển hình của chúng tôi.

Tìm hiểu cách tích hợp máy chủ WebSocket được viết bằng aiohttp vào dự án Django hiện có trong bài viết của chúng tôi. Hoặc học cách viết một cuộc trò chuyện đơn giản