Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng

Chúng tôi đang làm việc trong một dự án "Vấn đề về Generals Byzantine" với Python (ổ cắm), chúng tôi quản lý để tạo kết nối thành công giữa máy chủ và hai máy khách (client1, client2). Nhưng chúng tôi không biết làm thế nào để tạo kết nối giữa hai máy khách, bất kỳ sự trợ giúp nào?

Show

Vấn đề dự án mô hình liên kết: https://upload.wikimedia.org/wikipedia/commons/thumb/8/81/4generalestenientetraidor.svg/400px-4generalestenientetraidor.svg.png.png.

Server.py

import socket


host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)

serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

serv.bind((host, port))
serv.listen(5)

while True:
    conn, addr = serv.accept()
    conn.send(b"Attack ")
    data = conn.recv(4096)
    if not data: break
    print (data)

client1.py

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")

client2.py

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")

Ổ cắm và API ổ cắm được sử dụng để gửi tin nhắn trên mạng. Họ cung cấp một hình thức giao tiếp giữa các quá trình (IPC). Mạng có thể là một mạng cục bộ, logic vào máy tính hoặc một mạng được kết nối về mặt vật lý với mạng bên ngoài, với các kết nối riêng với các mạng khác. Ví dụ rõ ràng là Internet, mà bạn kết nối thông qua ISP của bạn.

Trong hướng dẫn này, bạn sẽ tạo ra:

  • Một máy chủ và máy khách ổ cắm đơn giảnsocket server and client
  • Một phiên bản cải tiến xử lý đồng thời nhiều kết nốimultiple connections simultaneously
  • Một ứng dụng máy chủ-khách hàng có chức năng giống như ứng dụng ổ cắm chính thức, hoàn chỉnh với tiêu đề và nội dung tùy chỉnh riêng của nósocket application, complete with its own custom header and content

Đến cuối hướng dẫn này, bạn sẽ hiểu cách sử dụng các chức năng và phương thức chính trong mô-đun ổ cắm Python, để viết các ứng dụng máy khách của riêng bạn. Bạn sẽ biết cách sử dụng một lớp tùy chỉnh để gửi tin nhắn và dữ liệu giữa các điểm cuối mà bạn có thể xây dựng và sử dụng cho các ứng dụng của riêng bạn.

Các ví dụ trong hướng dẫn này yêu cầu Python 3.6 trở lên, và đã được thử nghiệm bằng Python 3.10. Để tận dụng tối đa hướng dẫn này, tốt nhất là bạn nên tải xuống mã nguồn và có nó để tham khảo trong khi đọc:

Mạng và ổ cắm là những chủ đề lớn. Tập theo nghĩa đen đã được viết về chúng. Nếu bạn mới sử dụng ổ cắm hoặc kết nối mạng, thì điều đó hoàn toàn bình thường nếu bạn cảm thấy choáng ngợp với tất cả các thuật ngữ và mảnh.

Mặc dù vậy, don không được khuyến khích. Hướng dẫn này là dành cho bạn! Như với bất cứ điều gì liên quan đến Python, bạn có thể học một chút tại một thời điểm. Đánh dấu bài viết này và quay lại khi bạn đã sẵn sàng cho phần tiếp theo.

Tiểu sử

Ổ cắm có một lịch sử lâu dài. Việc sử dụng chúng bắt nguồn từ ARPANET vào năm 1971 và sau đó trở thành API trong Hệ điều hành Phân phối Phần mềm Berkeley (BSD) được phát hành năm 1983 có tên Berkeley Sockets.

Khi Internet cất cánh vào những năm 1990 với World Wide Web, lập trình mạng cũng vậy. Máy chủ web và trình duyệt weren là các ứng dụng duy nhất tận dụng các mạng mới được kết nối và sử dụng ổ cắm. Các ứng dụng máy khách-máy chủ của tất cả các loại và kích thước được sử dụng rộng rãi.

Ngày nay, mặc dù các giao thức cơ bản được sử dụng bởi API ổ cắm đã phát triển qua nhiều năm và các giao thức mới đã phát triển, API cấp thấp vẫn giữ nguyên.

Loại ứng dụng ổ cắm phổ biến nhất là các ứng dụng máy khách-máy khách, trong đó một bên hoạt động như máy chủ và chờ kết nối từ máy khách. Đây là loại ứng dụng mà bạn sẽ tạo trong hướng dẫn này. Cụ thể hơn, bạn sẽ tập trung vào API ổ cắm cho ổ cắm Internet, đôi khi được gọi là ổ cắm Berkeley hoặc BSD. Ngoài ra còn có các ổ cắm miền UNIX, chỉ có thể được sử dụng để giao tiếp giữa các quy trình trên cùng một máy chủ.

Tổng quan API ổ cắm

Mô -đun ổ cắm Python cung cấp giao diện cho API Berkeley Sockets. Đây là mô -đun mà bạn sẽ sử dụng trong hướng dẫn này.

Các hàm và phương thức API ổ cắm chính trong mô -đun này là:

  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    0
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    1
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    2
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    3
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    4
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    5
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    6
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    7
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    8

Python cung cấp một API thuận tiện và nhất quán ánh xạ trực tiếp vào các cuộc gọi hệ thống, các đối tác C. Trong phần tiếp theo, bạn sẽ học cách chúng được sử dụng cùng nhau.

Là một phần của thư viện tiêu chuẩn, Python cũng có các lớp giúp sử dụng các chức năng ổ cắm cấp thấp này dễ dàng hơn. Mặc dù nó không được đề cập trong hướng dẫn này, bạn có thể kiểm tra mô -đun Socketserver, một khung cho các máy chủ mạng. Ngoài ra còn có nhiều mô-đun có sẵn thực hiện các giao thức Internet cấp cao hơn như HTTP và SMTP. Để biết tổng quan, hãy xem các giao thức Internet và hỗ trợ.

Ổ cắm TCP

Bạn sẽ tạo một đối tượng ổ cắm bằng cách sử dụng

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9, chỉ định loại ổ cắm là
# echo-client.py

import socket

HOST = "127.0.0.1"  # The server's hostname or IP address
PORT = 65432  # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b"Hello, world")
    data = s.recv(1024)

print(f"Received {data!r}")
0. Khi bạn làm điều đó, giao thức mặc định mà sử dụng là Giao thức điều khiển truyền (TCP). Đây là một mặc định tốt và có lẽ những gì bạn muốn.

Tại sao bạn nên sử dụng TCP? Giao thức điều khiển truyền (TCP):

  • Là đáng tin cậy: các gói bị rơi trong mạng được phát hiện và truyền lại bởi người gửi. Packets dropped in the network are detected and retransmitted by the sender.
  • Có phân phối dữ liệu theo đơn đặt hàng: Dữ liệu được đọc bởi ứng dụng của bạn theo thứ tự được viết bởi người gửi. Data is read by your application in the order it was written by the sender.

Ngược lại, ổ cắm giao thức datagram của người dùng (UDP) được tạo bằng

# echo-client.py

import socket

HOST = "127.0.0.1"  # The server's hostname or IP address
PORT = 65432  # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b"Hello, world")
    data = s.recv(1024)

print(f"Received {data!r}")
1 aren đáng tin cậy và dữ liệu được đọc bởi người nhận có thể nằm ngoài thứ tự từ người gửi.

Tại sao nó quan trọng? Mạng là một hệ thống phân phối hiệu quả tốt nhất. Không có gì đảm bảo rằng dữ liệu của bạn sẽ đến đích hoặc bạn sẽ nhận được những gì đã được gửi cho bạn.

Các thiết bị mạng, chẳng hạn như bộ định tuyến và công tắc, có sẵn băng thông hữu hạn và đi kèm với các giới hạn hệ thống vốn có của riêng họ. Họ có CPU, bộ nhớ, xe buýt và bộ đệm gói giao diện, giống như máy khách và máy chủ của bạn. TCP giúp bạn không phải lo lắng về việc mất gói, việc đến ngoài thứ tự và những cạm bẫy khác luôn xảy ra khi bạn giao tiếp qua một mạng.

Để hiểu rõ hơn về điều này, hãy xem chuỗi các cuộc gọi API ổ cắm và luồng dữ liệu cho TCP:

Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng
Lưu lượng ổ cắm TCP (Nguồn hình ảnh)

Cột bên trái đại diện cho máy chủ. Ở phía bên tay phải là khách hàng.

Bắt đầu từ cột trên cùng bên trái, lưu ý các cuộc gọi API mà máy chủ thực hiện để thiết lập một ổ cắm nghe nghe của người dùng:

  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    0
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    1
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    2
  • # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    3

Một ổ cắm nghe làm những gì tên của nó gợi ý. Nó lắng nghe các kết nối từ khách hàng. Khi máy khách kết nối, máy chủ gọi

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
3 để chấp nhận hoặc hoàn thành kết nối.

Máy khách gọi

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
4 để thiết lập kết nối với máy chủ và bắt đầu bắt tay ba chiều. Bước bắt tay rất quan trọng vì nó đảm bảo rằng mỗi bên của kết nối có thể truy cập được trong mạng, nói cách khác là máy khách có thể tiếp cận máy chủ và ngược lại. Nó có thể chỉ là một máy chủ, máy khách hoặc máy chủ có thể tiếp cận bên kia.

Ở giữa là phần Trip Trip, trong đó dữ liệu được trao đổi giữa máy khách và máy chủ bằng cách sử dụng các cuộc gọi đến

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 và
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7.

Ở phía dưới, máy khách và máy chủ đóng ổ cắm tương ứng của họ.

Echo khách hàng và máy chủ

Bây giờ, bạn đã nhận được một cái nhìn tổng quan về API ổ cắm và cách khách hàng và máy chủ giao tiếp, bạn đã sẵn sàng để tạo máy khách và máy chủ đầu tiên của mình. Bạn sẽ bắt đầu với một triển khai đơn giản. Máy chủ chỉ đơn giản là lặp lại bất cứ điều gì nó nhận được trở lại với máy khách.

Máy chủ Echo

Đây là máy chủ:

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

Được rồi, vậy chính xác những gì đang xảy ra trong cuộc gọi API?

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9 Tạo một đối tượng ổ cắm hỗ trợ loại Trình quản lý ngữ cảnh, do đó bạn có thể sử dụng nó trong câu lệnh
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
1. Không cần phải gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
2:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().

Các đối số được chuyển đến

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
0 là các hằng số được sử dụng để chỉ định loại họ địa chỉ và loại ổ cắm.
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
4 là gia đình địa chỉ internet cho IPv4.
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
5 là loại ổ cắm cho TCP, giao thức sẽ được sử dụng để vận chuyển tin nhắn trong mạng.

Phương thức

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
1 được sử dụng để liên kết ổ cắm với giao diện mạng và số cổng cụ thể:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...

Các giá trị được truyền đến

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
1 phụ thuộc vào họ địa chỉ của ổ cắm. Trong ví dụ này, bạn đã sử dụng
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 (IPv4). Vì vậy, nó mong đợi một bộ hai:
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9.

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
00 có thể là tên máy chủ, địa chỉ IP hoặc chuỗi trống. Nếu một địa chỉ IP được sử dụng,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
00 phải là chuỗi địa chỉ có định dạng IPv4. Địa chỉ IP
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 là địa chỉ IPv4 tiêu chuẩn cho giao diện Loopback, do đó, chỉ các xử lý trên máy chủ mới có thể kết nối với máy chủ. Nếu bạn vượt qua một chuỗi trống, máy chủ sẽ chấp nhận kết nối trên tất cả các giao diện IPv4 có sẵn.

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
03 đại diện cho số cổng TCP để chấp nhận kết nối từ máy khách. Nó phải là một số nguyên từ
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
04 đến
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
05, vì
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
06 được bảo lưu. Một số hệ thống có thể yêu cầu các đặc quyền siêu nhân nếu số cổng nhỏ hơn
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
07.

Tại đây, một lưu ý về việc sử dụng tên máy chủ với

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
1:

Nếu bạn sử dụng tên máy chủ trong phần máy chủ của địa chỉ ổ cắm IPv4/V6, chương trình có thể hiển thị hành vi không xác định, vì Python sử dụng địa chỉ đầu tiên được trả về từ độ phân giải DNS. Địa chỉ ổ cắm sẽ được giải quyết khác nhau thành địa chỉ IPv4/V6 thực tế, tùy thuộc vào kết quả từ độ phân giải DNS và/hoặc cấu hình máy chủ. Đối với hành vi xác định, hãy sử dụng một địa chỉ số trong phần máy chủ. (Nguồn)

Bạn sẽ tìm hiểu thêm về điều này sau, trong việc sử dụng tên máy chủ. Hiện tại, chỉ cần hiểu rằng khi sử dụng tên máy chủ, bạn có thể thấy các kết quả khác nhau tùy thuộc vào những gì mà Lùi trả về từ quá trình giải quyết tên. Những kết quả này có thể là bất cứ điều gì. Lần đầu tiên bạn chạy ứng dụng của mình, bạn có thể nhận được địa chỉ ____10109. Lần tới, bạn nhận được một địa chỉ khác,

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
10. Lần thứ ba, bạn có thể nhận được
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
11, v.v.

Trong ví dụ máy chủ,

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
2 cho phép máy chủ chấp nhận kết nối. Nó làm cho máy chủ trở thành một ổ cắm của người khác:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...

Phương pháp

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
2 có tham số
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
14. Nó chỉ định số lượng các kết nối không được chấp nhận mà hệ thống sẽ cho phép trước khi từ chối các kết nối mới. Bắt đầu từ Python 3.5, nó tùy chọn. Nếu không được chỉ định, giá trị
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
14 mặc định được chọn.

Nếu máy chủ của bạn nhận được nhiều yêu cầu kết nối đồng thời, việc tăng giá trị

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
14 có thể giúp bằng cách đặt độ dài tối đa của hàng đợi cho các kết nối đang chờ xử lý. Giá trị tối đa phụ thuộc vào hệ thống. Ví dụ: trên Linux, xem
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
17.

Phương thức

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
3 chặn thực thi và chờ kết nối đến. Khi một máy khách kết nối, nó sẽ trả về một đối tượng ổ cắm mới đại diện cho kết nối và một tuple giữ địa chỉ của máy khách. Bộ tuple sẽ chứa
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9 cho các kết nối IPv4 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
20 cho IPv6. Xem các gia đình địa chỉ ổ cắm trong phần tham chiếu để biết chi tiết về các giá trị tuple.

Một điều mà bắt buộc phải hiểu là bây giờ bạn có một đối tượng ổ cắm mới từ

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
3. Điều này rất quan trọng bởi vì nó có một ổ cắm mà bạn sẽ sử dụng để giao tiếp với khách hàng. Nó khác biệt với ổ cắm nghe mà máy chủ đang sử dụng để chấp nhận các kết nối mới:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

Sau khi

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
3 cung cấp đối tượng ổ cắm máy khách
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
23, vòng lặp
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
24 vô hạn được sử dụng để lặp qua các cuộc gọi chặn đến
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
25. Điều này đọc bất kỳ dữ liệu nào mà khách hàng gửi và lặp lại nó bằng
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
26.

Nếu

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
25 trả về một đối tượng
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
28 trống,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
29, báo hiệu rằng máy khách đã đóng kết nối và vòng lặp bị chấm dứt. Câu lệnh
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
1 được sử dụng với
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
23 để tự động đóng ổ cắm ở cuối khối.

Echo khách hàng

Bây giờ hãy để Lừa nhìn vào khách hàng:

# echo-client.py

import socket

HOST = "127.0.0.1"  # The server's hostname or IP address
PORT = 65432  # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b"Hello, world")
    data = s.recv(1024)

print(f"Received {data!r}")

So với máy chủ, máy khách khá đơn giản. Nó tạo một đối tượng ổ cắm, sử dụng

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
4 để kết nối với máy chủ và gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
33 để gửi tin nhắn của nó. Cuối cùng, nó gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
34 để đọc trả lời máy chủ và sau đó in nó.

Chạy máy khách và máy chủ Echo

Trong phần này, bạn sẽ chạy máy khách và máy chủ để xem cách họ cư xử và kiểm tra những gì xảy ra.

Mở dấu nhắc thiết bị đầu cuối hoặc lệnh, điều hướng đến thư mục chứa các tập lệnh của bạn, đảm bảo rằng bạn đã cài đặt Python 3.6 trở lên và trên đường dẫn của bạn, sau đó chạy máy chủ:

Thiết bị đầu cuối của bạn sẽ xuất hiện để treo. Điều đó bởi vì máy chủ bị chặn, hoặc bị treo, trên

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
3:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

Nó chờ đợi một kết nối khách hàng. Bây giờ, hãy mở một cửa sổ hoặc dấu nhắc lệnh đầu cuối khác và chạy máy khách:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
0

Trong cửa sổ máy chủ, bạn nên nhận thấy một cái gì đó như thế này:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
1

Trong đầu ra ở trên, máy chủ đã in tuple

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
36 được trả về từ
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
37. Đây là địa chỉ IP của máy khách và số cổng TCP. Số cổng,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
38, rất có thể sẽ khác nhau khi bạn chạy nó trên máy của bạn.

Xem trạng thái ổ cắm

Để xem trạng thái hiện tại của ổ cắm trên máy chủ của bạn, hãy sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
39. Nó có sẵn theo mặc định trên MacOS, Linux và Windows.

Tại đây, đầu ra NetStat từ MacOS sau khi khởi động máy chủ:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
2

Lưu ý rằng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
40 là
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
41. Nếu
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
42 đã sử dụng
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
43 thay vì
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
44, NetStat sẽ hiển thị điều này:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
3

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
40 là
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
46, có nghĩa là tất cả các giao diện máy chủ có sẵn hỗ trợ họ địa chỉ sẽ được sử dụng để chấp nhận các kết nối đến. Trong ví dụ này,
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 đã được sử dụng (IPv4) trong cuộc gọi đến
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
0. Bạn có thể thấy điều này trong cột
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
49:
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
50.

Đầu ra ở trên được cắt để chỉ hiển thị máy chủ Echo. Bạn có thể thấy nhiều đầu ra hơn, tùy thuộc vào hệ thống mà bạn đang chạy nó. Những điều cần chú ý là các cột

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
49,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
40 và
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
53. Trong ví dụ cuối cùng ở trên, NetStat cho thấy máy chủ Echo đang sử dụng ổ cắm IPv4 TCP (
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
50), trên cổng 65432 trên tất cả các giao diện (
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
46) và nó ở trạng thái nghe (
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
56).

Một cách khác để truy cập này, cùng với thông tin hữu ích bổ sung, là sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
57 (liệt kê các tệp mở). Nó có sẵn theo mặc định trên macOS và có thể được cài đặt trên Linux bằng cách sử dụng trình quản lý gói của bạn, nếu nó chưa có:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
4

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
57 cung cấp cho bạn
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
59,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
60 (ID quy trình) và
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
61 (ID người dùng) của ổ cắm Internet mở khi được sử dụng với tùy chọn
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
62. Trên đây là quá trình máy chủ Echo.

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
39 và
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
57 có sẵn nhiều tùy chọn và khác nhau tùy thuộc vào hệ điều hành mà bạn đang chạy chúng. Kiểm tra trang
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
65 hoặc tài liệu cho cả hai. Họ chắc chắn đáng để dành một ít thời gian với và làm quen. Bạn sẽ được khen thưởng. Trên macOS và Linux, sử dụng
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
66 và
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
67. Đối với Windows, hãy sử dụng
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
68.

Ở đây, một lỗi phổ biến mà bạn sẽ gặp phải khi một nỗ lực kết nối được thực hiện vào một cổng không có ổ cắm nghe:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
5

Số cổng được chỉ định là sai hoặc máy chủ đang chạy. Hoặc có thể có một tường lửa trên đường dẫn mà chặn kết nối, có thể dễ dàng quên đi. Bạn cũng có thể thấy lỗi

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
69. Nhận một quy tắc tường lửa được thêm vào cho phép khách hàng kết nối với cổng TCP!

Có một danh sách các lỗi phổ biến trong phần tham chiếu.

Sự cố giao tiếp

Bây giờ bạn sẽ xem xét kỹ hơn về cách máy khách và máy chủ giao tiếp với nhau:

Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng

Khi sử dụng giao diện loopback (địa chỉ IPv4

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc địa chỉ IPv6
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71), dữ liệu không bao giờ rời khỏi máy chủ hoặc chạm vào mạng bên ngoài. Trong sơ đồ trên, giao diện loopback được chứa bên trong máy chủ. Điều này thể hiện bản chất bên trong của giao diện loopback và cho thấy rằng các kết nối và dữ liệu quá cảnh là cục bộ đến máy chủ. Đây là lý do tại sao bạn cũng sẽ nghe thấy giao diện Loopback và địa chỉ IP
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71 được gọi là Local localhost.

Các ứng dụng sử dụng giao diện Loopback để liên lạc với các quy trình khác chạy trên máy chủ và để bảo mật và cách ly khỏi mạng bên ngoài. Bởi vì nó nội bộ và chỉ có thể truy cập từ bên trong máy chủ, nên nó không bị lộ.

Bạn có thể thấy điều này trong hành động nếu bạn có một máy chủ ứng dụng sử dụng cơ sở dữ liệu riêng của nó. Nếu nó không phải là cơ sở dữ liệu được sử dụng bởi các máy chủ khác, thì nó có thể được cấu hình để nghe các kết nối trên giao diện Loopback. Nếu đây là trường hợp, các máy chủ khác trên mạng có thể kết nối với nó.

Khi bạn sử dụng địa chỉ IP khác ngoài

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71 trong các ứng dụng của bạn, nó có thể bị ràng buộc với giao diện Ethernet mà kết nối với mạng bên ngoài. Đây là cửa ngõ của bạn đến các máy chủ khác bên ngoài vương quốc Local Localhost của bạn:

Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng

Hãy cẩn thận ở ngoài đó. Nó là một thế giới khó chịu, độc ác. Hãy chắc chắn đọc phần bằng cách sử dụng tên máy chủ trước khi mạo hiểm từ giới hạn an toàn của địa phương. Có một ghi chú bảo mật áp dụng ngay cả khi bạn không sử dụng tên máy chủ nhưng chỉ sử dụng địa chỉ IP.

Xử lý nhiều kết nối

Máy chủ Echo chắc chắn có những hạn chế của nó. Điều lớn nhất là nó chỉ phục vụ một khách hàng và sau đó thoát ra. Khách hàng Echo cũng có giới hạn này, nhưng có một vấn đề bổ sung. Khi khách hàng sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
34, có thể nó sẽ chỉ trả về một byte,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
77 từ
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
78:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
6

Đối số

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
79 của
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
07 được sử dụng ở trên là lượng dữ liệu tối đa được nhận cùng một lúc. Nó không có nghĩa là
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7 sẽ trả lại
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
07 byte.

Phương pháp

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 cũng hành xử theo cách này. Nó trả về số byte được gửi, có thể nhỏ hơn kích thước của dữ liệu được truyền vào. Bạn có trách nhiệm kiểm tra điều này và gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 nhiều lần khi cần gửi tất cả dữ liệu:

Các ứng dụng có trách nhiệm kiểm tra xem tất cả dữ liệu đã được gửi; Nếu chỉ có một số dữ liệu được truyền đi, ứng dụng cần thử phân phối dữ liệu còn lại. (Nguồn)

Trong ví dụ trên, bạn đã tránh phải làm điều này bằng cách sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
85:

Không giống như Send (), phương thức này tiếp tục gửi dữ liệu từ byte cho đến khi tất cả dữ liệu đã được gửi hoặc xảy ra lỗi.

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
86 được trả lại trên thành công. (Nguồn)

Bạn có hai vấn đề vào thời điểm này:

  • Làm thế nào để bạn xử lý nhiều kết nối đồng thời?
  • Bạn cần gọi
    # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    6 và
    # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    
    7 cho đến khi tất cả dữ liệu được gửi hoặc nhận.

Bạn có thể làm gì? Có nhiều cách tiếp cận để đồng thời. Một cách tiếp cận phổ biến là sử dụng I/O không đồng bộ.

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
89 đã được đưa vào thư viện tiêu chuẩn trong Python 3.4. Sự lựa chọn truyền thống là sử dụng chủ đề.

Vấn đề với sự đồng thời là nó khó có thể đi đúng. Có nhiều sự tinh tế để xem xét và bảo vệ chống lại. Tất cả chỉ là một trong những điều này để thể hiện chính nó và ứng dụng của bạn có thể đột nhiên thất bại theo những cách không tinh tế.

Điều này có nghĩa là khiến bạn sợ hãi khi học và sử dụng lập trình đồng thời. Nếu ứng dụng của bạn cần mở rộng quy mô, thì đó là một điều cần thiết nếu bạn muốn sử dụng nhiều hơn một bộ xử lý hoặc một lõi. Tuy nhiên, đối với hướng dẫn này, bạn sẽ sử dụng một cái gì đó mà thậm chí còn truyền thống hơn các chủ đề và dễ lý luận hơn. Bạn sẽ sử dụng ông nội của các cuộc gọi hệ thống:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90.

Phương pháp

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 cho phép bạn kiểm tra hoàn thành I/O trên nhiều ổ cắm. Vì vậy, bạn có thể gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 để xem ổ cắm nào có I/O sẵn sàng để đọc và/hoặc viết. Nhưng đây là Python, vì vậy có nhiều hơn nữa. Bạn sẽ sử dụng mô -đun bộ chọn trong thư viện tiêu chuẩn để việc triển khai hiệu quả nhất được sử dụng, bất kể hệ điều hành mà bạn tình cờ đang chạy:

Mô-đun này cho phép ghép kênh I/O cấp cao và hiệu quả, được xây dựng trên các nguyên thủy mô-đun chọn. Thay vào đó, người dùng được khuyến khích sử dụng mô-đun này, trừ khi họ muốn kiểm soát chính xác các nguyên thủy cấp hệ điều hành được sử dụng. (Nguồn)

Tuy nhiên, bằng cách sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90, bạn không thể chạy đồng thời. Điều đó nói rằng, tùy thuộc vào khối lượng công việc của bạn, phương pháp này có thể vẫn rất nhanh. Nó phụ thuộc vào những gì ứng dụng của bạn cần làm khi nó phục vụ một yêu cầu và số lượng khách hàng cần hỗ trợ.

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
89 sử dụng đa nhiệm hợp tác đơn luồng và vòng lặp sự kiện để quản lý các tác vụ. Với
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90, bạn sẽ viết phiên bản của một vòng lặp sự kiện, mặc dù đơn giản và đồng bộ hơn. Khi sử dụng nhiều luồng, mặc dù bạn có đồng thời, hiện tại bạn phải sử dụng GIL (khóa phiên dịch toàn cầu) với CPython và Pypy. Điều này có hiệu quả giới hạn số lượng công việc bạn có thể làm song song.

Đây là tất cả để nói rằng sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 có thể là một lựa chọn hoàn toàn tốt. Don cảm thấy như bạn phải sử dụng
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
89, chủ đề hoặc thư viện không đồng bộ mới nhất. Thông thường, trong một ứng dụng mạng, ứng dụng của bạn dù sao cũng bị ràng buộc I/O: nó có thể đang chờ trên mạng cục bộ, cho các điểm cuối ở phía bên kia của mạng, cho đĩa ghi, v.v.

Nếu bạn nhận được yêu cầu từ các khách hàng bắt đầu công việc ràng buộc CPU, hãy xem mô -đun đồng thời. Nó chứa lớp ProcessPoolExecutor, sử dụng một nhóm quy trình để thực hiện các cuộc gọi không đồng bộ.

Nếu bạn sử dụng nhiều quy trình, hệ điều hành có thể lên lịch mã Python của bạn để chạy song song trên nhiều bộ xử lý hoặc lõi, mà không cần Gil. Để biết ý tưởng và cảm hứng, hãy xem Pycon Talk John Reese - Suy nghĩ bên ngoài Gil với Asyncio và Multiprocessing - Pycon 2018.

Trong phần tiếp theo, bạn sẽ xem xét các ví dụ về một máy chủ và máy khách giải quyết các vấn đề này. Họ sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 để xử lý đồng thời nhiều kết nối và gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 và
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7 bao nhiêu lần nếu cần.

Máy khách và máy chủ đa kết nối

Trong hai phần tiếp theo, bạn sẽ tạo một máy chủ và máy khách xử lý nhiều kết nối bằng cách sử dụng đối tượng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
01 được tạo từ mô -đun chọn lọc.

Máy chủ đa kết nối

Đầu tiên, chuyển sự chú ý của bạn sang máy chủ đa kết nối. Phần đầu tiên thiết lập ổ cắm nghe:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
7

Sự khác biệt lớn nhất giữa máy chủ này và máy chủ Echo là cuộc gọi đến

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
02 để định cấu hình ổ cắm ở chế độ không chặn. Các cuộc gọi được thực hiện cho ổ cắm này sẽ không còn chặn. Khi nó được sử dụng với
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
03, như bạn sẽ thấy bên dưới, bạn có thể đợi các sự kiện trên một hoặc nhiều ổ cắm và sau đó đọc và ghi dữ liệu khi nó sẵn sàng.

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
04 đăng ký ổ cắm được theo dõi với
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
03 cho các sự kiện mà bạn quan tâm. Đối với ổ cắm nghe, bạn muốn đọc các sự kiện:
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
06.

Để lưu trữ bất kỳ dữ liệu tùy ý nào mà bạn thích cùng với ổ cắm, bạn sẽ sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
07. Nó đã trở lại khi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 trở lại. Bạn sẽ sử dụng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
07 để theo dõi những gì mà Lừa đã được gửi và nhận trên ổ cắm.

Tiếp theo là vòng lặp sự kiện:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
8

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
10 Khối cho đến khi có các ổ cắm sẵn sàng cho I/O. Nó trả về một danh sách các bộ dữ liệu, một cho mỗi ổ cắm. Mỗi tuple chứa một
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
11 và
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
12.
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
11 là một selectorKey
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
14 chứa thuộc tính
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
15.
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
16 là đối tượng ổ cắm và
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
12 là mặt nạ sự kiện của các hoạt động đã sẵn sàng.

Nếu

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
18 là
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
86, thì bạn sẽ biết nó từ ổ cắm nghe và bạn cần chấp nhận kết nối. Bạn sẽ gọi chức năng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
20 của riêng bạn để lấy đối tượng ổ cắm mới và đăng ký nó bằng bộ chọn. Bạn sẽ nhìn vào điều đó trong một khoảnh khắc.

Nếu

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
18 không phải là
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
86, thì bạn sẽ biết đó là một ổ cắm khách hàng mà Lừa đã được chấp nhận và bạn cần phải phục vụ nó.
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
23 sau đó được gọi với
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
11 và
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
12 làm đối số, và đó là mọi thứ bạn cần để vận hành trên ổ cắm.

Đây là những gì chức năng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
20 của bạn làm:

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
9

Bởi vì ổ cắm nghe đã được đăng ký cho sự kiện

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
06, nên nó sẽ sẵn sàng để đọc. Bạn gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
28 và sau đó gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
29 để đặt ổ cắm ở chế độ không chặn.

Hãy nhớ rằng, đây là mục tiêu chính trong phiên bản này của máy chủ vì bạn không muốn nó chặn. Nếu nó chặn, thì toàn bộ máy chủ bị đình trệ cho đến khi nó trở lại. Điều đó có nghĩa là các ổ cắm khác được chờ đợi mặc dù máy chủ không tích cực hoạt động. Đây là trạng thái Hang Hang đáng sợ mà bạn không muốn máy chủ của bạn được sử dụng.

Tiếp theo, bạn tạo một đối tượng để giữ dữ liệu mà bạn muốn bao gồm cùng với ổ cắm bằng cách sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
30. Bởi vì bạn muốn biết khi nào kết nối máy khách đã sẵn sàng để đọc và viết, cả hai sự kiện đó đều được đặt với bitwise hoặc toán tử:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
0

Mặt nạ

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
31 đối tượng, ổ cắm và dữ liệu sau đó được truyền đến
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
04.

Bây giờ hãy xem

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
23 để xem kết nối máy khách được xử lý như thế nào khi nó sẵn sàng:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
1

Đây là trung tâm của máy chủ đa kết nối đơn giản.

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
11 là
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
14 được trả về từ
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 có chứa đối tượng ổ cắm (
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
15) và đối tượng dữ liệu.
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
12 chứa các sự kiện đã sẵn sàng.

Nếu ổ cắm đã sẵn sàng để đọc, thì

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
39 sẽ đánh giá thành
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
40, do đó
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
41 được gọi. Bất kỳ dữ liệu nào mà đọc được được thêm vào
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
42 để nó có thể được gửi sau.

Lưu ý khối

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
43 để kiểm tra xem không có dữ liệu nào được nhận:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
2

Nếu không nhận được dữ liệu, điều này có nghĩa là máy khách đã đóng ổ cắm của họ, vì vậy máy chủ cũng vậy. Nhưng don không quên gọi

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
44 trước khi đóng, vì vậy, nó không còn được theo dõi bởi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90.

Khi ổ cắm đã sẵn sàng để viết, điều này phải luôn luôn là trường hợp của ổ cắm khỏe mạnh, bất kỳ dữ liệu nhận được nào được lưu trữ trong

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
42 đều được lặp lại với máy khách bằng cách sử dụng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
47. Các byte được gửi sau đó được xóa khỏi bộ đệm gửi:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
3

Phương thức

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 trả về số byte được gửi. Số này sau đó có thể được sử dụng với ký hiệu lát cắt trên bộ đệm
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
49 để loại bỏ các byte được gửi.

Máy khách đa kết nối

Bây giờ hãy xem máy khách đa kết nối,

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
50. Nó rất giống với máy chủ, nhưng thay vì nghe các kết nối, nó bắt đầu bằng cách bắt đầu kết nối thông qua
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
51:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
4

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
52 được đọc từ dòng lệnh và là số lượng kết nối để tạo cho máy chủ. Giống như máy chủ, mỗi ổ cắm được đặt thành chế độ không chặn.

Bạn sử dụng

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
5 thay vì
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
4 vì
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
4 sẽ ngay lập tức tăng ngoại lệ
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
56. Phương thức
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
5 ban đầu trả về một chỉ báo lỗi,
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
58, thay vì nêu ra một ngoại lệ sẽ can thiệp vào kết nối đang diễn ra. Khi kết nối được hoàn thành, ổ cắm đã sẵn sàng để đọc và viết và được trả lại bởi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90.

Sau khi ổ cắm được thiết lập, dữ liệu bạn muốn lưu trữ với ổ cắm được tạo bằng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
30. Các tin nhắn mà máy khách sẽ gửi đến máy chủ được sao chép bằng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
61 vì mỗi kết nối sẽ gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
62 và sửa đổi danh sách. Mọi thứ cần thiết để theo dõi những gì khách hàng cần gửi, đã gửi và nhận được, bao gồm tổng số byte trong tin nhắn, được lưu trữ trong đối tượng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
07.

Kiểm tra các thay đổi được thực hiện từ máy chủ

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
23 cho phiên bản máy khách:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
5

Nó về cơ bản giống nhau nhưng đối với một sự khác biệt quan trọng. Máy khách theo dõi số lượng byte mà nó nhận được từ máy chủ để có thể đóng bên cạnh kết nối. Khi máy chủ phát hiện ra điều này, nó cũng đóng mặt của kết nối.

Lưu ý rằng bằng cách thực hiện điều này, máy chủ phụ thuộc vào máy khách được hành động tốt: máy chủ hy vọng máy khách sẽ đóng phía kết nối của nó khi nó thực hiện gửi tin nhắn. Nếu máy khách không đóng, máy chủ sẽ để kết nối mở. Trong một ứng dụng thực sự, bạn có thể muốn bảo vệ chống lại điều này trong máy chủ của mình bằng cách triển khai thời gian chờ để ngăn chặn các kết nối máy khách tích lũy nếu họ không gửi yêu cầu sau một khoảng thời gian nhất định.

Chạy máy khách và máy chủ đa kết nối

Bây giờ, thời gian để chạy

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
65 và
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
50. Cả hai đều sử dụng các đối số dòng lệnh. Bạn có thể chạy chúng mà không cần đối số để xem các tùy chọn.

Đối với máy chủ, hãy vượt qua số

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
00 và
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
03:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
6

Đối với máy khách, cũng chuyển số lượng kết nối để tạo cho máy chủ,

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
69:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
7

Dưới đây là đầu ra của máy chủ khi nghe trên giao diện loopback trên cổng 65432:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
8

Dưới đây là đầu ra của máy khách khi nó tạo hai kết nối với máy chủ ở trên:

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
9

Tuyệt quá! Bây giờ bạn đã chạy máy khách và máy chủ đa kết nối. Trong phần tiếp theo, bạn sẽ lấy ví dụ này hơn nữa.

Ứng dụng khách hàng và máy chủ

Ví dụ về máy khách và máy chủ đa kết nối chắc chắn là một cải tiến so với nơi bạn bắt đầu. Tuy nhiên, bây giờ bạn có thể thực hiện thêm một bước và giải quyết các thiếu sót của ví dụ

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
70 trước đó trong một triển khai cuối cùng: máy khách và máy chủ ứng dụng.

Bạn muốn một máy khách và máy chủ xử lý các lỗi một cách thích hợp để các kết nối khác bị ảnh hưởng. Rõ ràng, khách hàng hoặc máy chủ của bạn không nên rơi xuống trong một quả bóng giận dữ nếu một ngoại lệ không bị bắt. Đây là điều mà bạn đã phải lo lắng cho đến bây giờ, bởi vì các ví dụ đã cố tình bỏ qua việc xử lý lỗi cho sự ngắn gọn và rõ ràng.

Bây giờ, bạn đã quen thuộc với API cơ bản, ổ cắm không chặn và

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90, bạn có thể thêm một số xử lý lỗi và giải quyết con voi trong phòng, mà các ví dụ đã giấu bạn đằng sau bức màn lớn ở đó. Hãy nhớ rằng lớp tùy chỉnh đã được đề cập trở lại trong phần giới thiệu? Đó là những gì bạn sẽ khám phá tiếp theo.

Đầu tiên, bạn sẽ giải quyết các lỗi:

Tất cả các lỗi đều tăng ngoại lệ. Các ngoại lệ bình thường cho các loại đối số không hợp lệ và các điều kiện ngoài bộ nhớ có thể được nêu ra; Bắt đầu từ Python 3.3, các lỗi liên quan đến ổ cắm hoặc ngữ nghĩa địa chỉ tăng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
72 hoặc một trong các lớp con của nó. (Nguồn)

Vì vậy, một điều bạn cần làm là bắt

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
72. Một cân nhắc quan trọng khác liên quan đến lỗi là thời gian chờ. Bạn sẽ thấy họ được thảo luận ở nhiều nơi trong tài liệu. Thời gian chờ xảy ra và là một lỗi được gọi là lỗi bình thường. Máy chủ và bộ định tuyến được khởi động lại, các cổng chuyển đổi xấu, dây cáp trở nên xấu, dây cáp bị rút phích cắm, bạn đặt tên cho nó. Bạn nên chuẩn bị cho những lỗi này và các lỗi khác, xử lý chúng trong mã của bạn.timeouts. You’ll see them discussed in many places in the documentation. Timeouts happen and are a so-called normal error. Hosts and routers are rebooted, switch ports go bad, cables go bad, cables get unplugged, you name it. You should be prepared for these and other errors, handling them in your code.

Còn con voi trong phòng thì sao? Như được gợi ý bởi loại ổ cắm

# echo-client.py

import socket

HOST = "127.0.0.1"  # The server's hostname or IP address
PORT = 65432  # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b"Hello, world")
    data = s.recv(1024)

print(f"Received {data!r}")
0, khi sử dụng TCP, bạn đã đọc từ một dòng byte liên tục. Nó giống như đọc từ một tệp trên đĩa, nhưng thay vào đó, bạn đã đọc các byte từ mạng. Tuy nhiên, không giống như đọc một tệp, ở đó không có
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
75.

Nói cách khác, bạn có thể định vị lại vị trí con trỏ ổ cắm, nếu có một, và di chuyển xung quanh dữ liệu.

Khi byte đến ổ cắm của bạn, có bộ đệm mạng liên quan. Một khi bạn đã đọc chúng, chúng cần được lưu ở đâu đó, nếu không bạn sẽ bỏ chúng. Gọi

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7 một lần nữa đọc luồng byte tiếp theo có sẵn từ ổ cắm.

Bạn sẽ đọc từ ổ cắm trong các khối. Vì vậy, bạn cần gọi

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7 và lưu dữ liệu trong bộ đệm cho đến khi bạn đọc đủ byte để có một thông báo hoàn chỉnh có ý nghĩa với ứng dụng của bạn.

Nó tùy thuộc vào bạn để xác định và theo dõi vị trí của các ranh giới thông điệp. Theo như ổ cắm TCP, nó chỉ gửi và nhận các byte thô đến và từ mạng. Nó không biết gì về những byte thô đó có nghĩa là gì.

Đây là lý do tại sao bạn cần xác định giao thức lớp ứng dụng. Những gì một giao thức lớp ứng dụng? Nói một cách đơn giản, ứng dụng của bạn sẽ gửi và nhận tin nhắn. Định dạng của các tin nhắn này là giao thức ứng dụng của bạn.

Nói cách khác, độ dài và định dạng mà bạn chọn cho các thông báo này xác định ngữ nghĩa và hành vi của ứng dụng của bạn. Điều này liên quan trực tiếp đến những gì bạn đã học trong đoạn trước về việc đọc byte từ ổ cắm. Khi bạn đọc các byte với

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7, bạn cần theo kịp số lượng byte đã được đọc và tìm ra ranh giới thông điệp ở đâu.

Làm thế nào bạn có thể làm điều này? Một cách là luôn luôn gửi tin nhắn có độ dài cố định. Nếu họ luôn luôn có cùng kích thước, thì nó dễ dàng. Khi bạn đọc số byte đó vào bộ đệm, thì bạn biết bạn có một tin nhắn đầy đủ.

Tuy nhiên, việc sử dụng các tin nhắn có độ dài cố định là không hiệu quả cho các tin nhắn nhỏ nơi bạn cần sử dụng đệm để điền vào chúng. Ngoài ra, bạn vẫn còn để lại vấn đề phải làm gì về dữ liệu không phù hợp với một tin nhắn.

Trong hướng dẫn này, bạn sẽ học được một cách tiếp cận chung, một cách mà sử dụng bởi nhiều giao thức, bao gồm cả HTTP. Bạn có thể các tin nhắn tiền tố có tiêu đề bao gồm độ dài nội dung cũng như bất kỳ trường nào khác bạn cần. Bằng cách này, bạn sẽ chỉ cần theo kịp tiêu đề. Khi bạn đã đọc tiêu đề, bạn có thể xử lý nó để xác định độ dài của nội dung tin nhắn. Với độ dài nội dung, sau đó bạn có thể đọc số byte đó để tiêu thụ nó.header that includes the content length as well as any other fields you need. By doing this, you’ll only need to keep up with the header. Once you’ve read the header, you can process it to determine the length of the message’s content. With the content length, you can then read that number of bytes to consume it.

Bạn sẽ thực hiện điều này bằng cách tạo một lớp tùy chỉnh có thể gửi và nhận tin nhắn có chứa dữ liệu văn bản hoặc nhị phân. Bạn có thể cải thiện và mở rộng lớp này cho các ứng dụng của riêng bạn. Điều quan trọng nhất là bạn sẽ có thể thấy một ví dụ về cách thực hiện điều này.

Trước khi bạn bắt đầu, có một cái gì đó bạn cần biết về ổ cắm và byte. Như bạn đã học trước đó, khi gửi và nhận dữ liệu qua ổ cắm, bạn đã gửi và nhận các byte thô.

Nếu bạn nhận được dữ liệu và muốn sử dụng nó trong một bối cảnh mà nó được giải thích là nhiều byte, ví dụ như một số nguyên 4 byte, bạn sẽ cần phải tính đến rằng nó có thể ở định dạng mà không có nguồn gốc từ máy CPU của bạn. Máy khách hoặc máy chủ ở đầu bên kia có thể có CPU sử dụng đơn đặt hàng byte khác với của bạn. Nếu đây là trường hợp, thì bạn sẽ cần phải chuyển đổi nó sang thứ tự byte gốc của máy chủ trước khi sử dụng nó.

Thứ tự byte này được gọi là một endianness CPU. Xem byte endianness trong phần tham chiếu để biết chi tiết. Bạn sẽ tránh được vấn đề này bằng cách tận dụng Unicode cho tiêu đề tin nhắn của bạn và sử dụng UTF-8 mã hóa. Vì UTF-8 sử dụng mã hóa 8 bit, không có vấn đề đặt hàng byte nào.

Bạn có thể tìm thấy một lời giải thích trong mã hóa Python và tài liệu Unicode. Lưu ý rằng điều này chỉ áp dụng cho tiêu đề văn bản. Bạn sẽ sử dụng một loại rõ ràng và mã hóa được xác định trong tiêu đề cho nội dung mà Lừa được gửi, tải trọng tin nhắn. Điều này sẽ cho phép bạn chuyển bất kỳ dữ liệu nào mà bạn thích (văn bản hoặc nhị phân), ở bất kỳ định dạng nào.

Bạn có thể dễ dàng xác định thứ tự byte của máy bằng cách sử dụng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
79. Ví dụ, bạn có thể thấy một cái gì đó như thế này:

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
0

Nếu bạn chạy điều này trong một máy ảo mô phỏng CPU lớn (PowerPC), thì một cái gì đó như thế này sẽ xảy ra:

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
1

Trong ứng dụng ví dụ này, giao thức lớp ứng dụng của bạn định nghĩa tiêu đề là văn bản Unicode với mã hóa UTF-8. Đối với nội dung thực tế trong tin nhắn, tải trọng tin nhắn, bạn sẽ vẫn phải trao đổi thứ tự byte theo cách thủ công nếu cần.

Điều này sẽ phụ thuộc vào ứng dụng của bạn và liệu nó có cần xử lý dữ liệu nhị phân đa byte từ một máy có độ chính xác khác hay không. Bạn có thể giúp khách hàng hoặc máy chủ của mình triển khai hỗ trợ nhị phân bằng cách thêm các tiêu đề bổ sung và sử dụng chúng để truyền các tham số, tương tự như HTTP.

Don Tiết lo lắng nếu điều này không có ý nghĩa gì. Trong phần tiếp theo, bạn sẽ thấy tất cả những điều này hoạt động và phù hợp với nhau như thế nào.

Gửi tin nhắn ứng dụng

Vẫn còn một chút vấn đề. Bạn có một tiêu đề có độ dài thay đổi, rất đẹp và linh hoạt, nhưng làm thế nào để bạn biết độ dài của tiêu đề khi đọc nó với

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7?

Khi bạn đã biết trước đây về việc sử dụng

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7 và ranh giới tin nhắn, bạn cũng đã học được rằng các tiêu đề có độ dài cố định có thể không hiệu quả. Điều đó đúng, nhưng bạn sẽ sử dụng một tiêu đề nhỏ, 2 byte, có độ dài cố định để có tiền tố tiêu đề JSON chứa độ dài của nó.

Bạn có thể nghĩ về điều này như một cách tiếp cận lai để gửi tin nhắn. Trên thực tế, bạn đã khởi động quá trình nhận thông báo bằng cách gửi độ dài của tiêu đề trước. Điều này giúp người nhận của bạn dễ dàng giải mã thông điệp.

Để cung cấp cho bạn ý tưởng tốt hơn về định dạng tin nhắn, hãy xem toàn bộ tin nhắn:

Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng

Một thông báo bắt đầu với một tiêu đề có độ dài cố định của hai byte, là một số nguyên theo thứ tự byte mạng. Đây là độ dài của tiêu đề tiếp theo, tiêu đề JSON có độ dài thay đổi. Khi bạn đã đọc hai byte với

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7, thì bạn biết bạn có thể xử lý hai byte dưới dạng số nguyên và sau đó đọc số byte đó trước khi giải mã tiêu đề UTF-8 JSON.

Tiêu đề JSON chứa một từ điển của các tiêu đề bổ sung. Một trong số đó là

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
83, đó là số byte của nội dung tin nhắn (không bao gồm tiêu đề JSON). Khi bạn đã gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7 và đọc byte
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
83, thì bạn đã đạt đến một ranh giới tin nhắn, có nghĩa là bạn đã đọc toàn bộ tin nhắn.

Lớp thông báo ứng dụng

Cuối cùng, tiền thưởng! Trong phần này, bạn sẽ nghiên cứu lớp

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 và xem cách mà nó được sử dụng với
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 khi đọc và viết các sự kiện xảy ra trên ổ cắm.

Ứng dụng ví dụ này phản ánh những loại tin nhắn mà máy khách và máy chủ có thể sử dụng hợp lý. Bạn vượt xa khách hàng và máy chủ đồ chơi Echo tại thời điểm này!

Để giữ cho mọi thứ đơn giản và vẫn chứng minh mọi thứ sẽ hoạt động như thế nào trong một ứng dụng thực, ví dụ này sử dụng giao thức ứng dụng thực hiện một tính năng tìm kiếm cơ bản. Máy khách gửi yêu cầu tìm kiếm và máy chủ thực hiện tìm kiếm một trận đấu. Nếu yêu cầu được gửi bởi khách hàng được công nhận là tìm kiếm, máy chủ giả định rằng đó là một yêu cầu nhị phân và trả về phản hồi nhị phân.

Sau khi đọc các phần sau, chạy các ví dụ và thử nghiệm mã, bạn sẽ thấy mọi thứ hoạt động như thế nào. Sau đó, bạn có thể sử dụng lớp

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 làm điểm bắt đầu và sửa đổi nó cho mục đích sử dụng của riêng bạn.

Ứng dụng này không xa so với ví dụ máy khách và máy chủ

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
70. Mã vòng lặp sự kiện vẫn giữ nguyên trong
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
90 và
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
91. Những gì bạn sẽ làm là chuyển mã tin nhắn vào một lớp có tên
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 và thêm các phương thức để hỗ trợ đọc, viết và xử lý các tiêu đề và nội dung. Đây là một ví dụ tuyệt vời để sử dụng một lớp.

Như bạn đã biết trước đây và bạn sẽ thấy bên dưới, làm việc với các ổ cắm liên quan đến việc giữ trạng thái. Bằng cách sử dụng một lớp, bạn giữ tất cả trạng thái, dữ liệu và mã được gói cùng nhau trong một đơn vị có tổ chức. Một thể hiện của lớp được tạo cho mỗi ổ cắm trong máy khách và máy chủ khi kết nối được bắt đầu hoặc chấp nhận.

Lớp chủ yếu giống nhau cho cả máy khách và máy chủ cho các phương thức trình bao bọc và tiện ích. Họ bắt đầu với một dấu gạch dưới, như

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
93. Các phương pháp này đơn giản hóa làm việc với lớp. Họ giúp đỡ các phương pháp khác bằng cách cho phép chúng ngắn hơn và hỗ trợ nguyên tắc khô.

Lớp máy chủ ____ ____286 hoạt động theo cách tương tự như máy khách và ngược lại. Sự khác biệt là máy khách bắt đầu kết nối và gửi thông báo yêu cầu, theo sau là xử lý thông báo phản hồi máy chủ. Ngược lại, máy chủ chờ kết nối, xử lý thông báo yêu cầu của máy khách và sau đó gửi tin nhắn phản hồi.

Có vẻ như thế này:

BươcĐiểm cuốiNội dung hành động / tin nhắn
1 Khách hàngGửi nội dung yêu cầu chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
2 Người phục vụNhận và xử lý yêu cầu khách hàng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
3 Người phục vụNhận và xử lý yêu cầu khách hàng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
4 Khách hàngGửi nội dung yêu cầu chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86

Người phục vụ

Nhận và xử lý yêu cầu khách hàng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Gửi nội dung phản hồi có chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Nhận và xử lý phản hồi máy chủ
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Người phục vụNhận và xử lý yêu cầu khách hàng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Gửi nội dung phản hồi có chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Người phục vụNhận và xử lý yêu cầu khách hàng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Gửi nội dung phản hồi có chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Khách hàngGửi nội dung yêu cầu chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Người phục vụ
Khách hàngGửi nội dung yêu cầu chứa
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86
Người phục vụ

Nhận và xử lý yêu cầu khách hàng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86

Gửi nội dung phản hồi có chứa

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86

Nhận và xử lý phản hồi máy chủ

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86

Tại đây, tập tin và bố cục mã:

Đăng kí

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
3

Tập tin

Mã số

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
4

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
91

Kịch bản chính của máy chủ

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
00

Lớp máy chủ ____ ____286

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
90

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
5

Kịch bản chính của khách hàng

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
03

Lớp khách hàng ____ ____286

Điểm vào tin nhắnHiểu cách thức hoạt động của lớp
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 có thể là một thách thức bởi vì có một khía cạnh của thiết kế của nó có thể không rõ ràng ngay lập tức. Tại sao? Quản lý trạng thái.
Sau khi một đối tượng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 được tạo, nó liên kết với một ổ cắm mà theo dõi các sự kiện bằng cách sử dụng
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
07:
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
2
Khi các sự kiện đã sẵn sàng trên ổ cắm, họ đã được trả lại bởi
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
08. Sau đó, bạn có thể lấy lại tham chiếu trở lại đối tượng tin nhắn bằng thuộc tính
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
07 trên đối tượng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
11 và gọi một phương thức trong
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86:
Nhìn vào vòng lặp sự kiện ở trên, bạn sẽ thấy
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
03 nằm ở ghế lái. Nó chặn, chờ đợi ở đầu vòng lặp cho các sự kiện. Nó có trách nhiệm thức dậy khi đọc và viết các sự kiện đã sẵn sàng để được xử lý trên ổ cắm. Điều đó có nghĩa là, một cách gián tiếp, nó cũng chịu trách nhiệm gọi phương thức
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13. Đó là lý do tại sao
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13 là điểm nhập cảnh.
Ở đây, những gì phương pháp
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13 làm:
Điều đó tốt:
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13 rất đơn giản. Nó chỉ có thể làm hai điều: Gọi
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
17 và
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18.
Đây là nơi quản lý trạng thái xuất hiện. Nếu một phương pháp khác phụ thuộc vào các biến trạng thái có một giá trị nhất định, thì chúng sẽ chỉ được gọi từ
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
17 và
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18. Điều này giữ cho logic đơn giản nhất có thể như các sự kiện xuất hiện trên ổ cắm để xử lý.
Bạn có thể bị cám dỗ sử dụng hỗn hợp một số phương thức kiểm tra các biến trạng thái hiện tại và, tùy thuộc vào giá trị của chúng, hãy gọi các phương thức khác để xử lý dữ liệu bên ngoài
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
17 hoặc
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18. Cuối cùng, điều này có thể sẽ chứng minh quá phức tạp để quản lý và theo kịp.
Bạn chắc chắn nên sửa đổi lớp cho phù hợp với nhu cầu của riêng bạn để nó phù hợp nhất với bạn, nhưng có lẽ bạn sẽ có kết quả tốt nhất nếu bạn kiểm tra trạng thái và các cuộc gọi đến các phương thức phụ thuộc vào trạng thái đó với các phương thức
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
17 và
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18 nếu có thể.
Bây giờ hãy nhìn vào
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
17. Đây là phiên bản máy chủ, nhưng máy khách là như nhau. Nó chỉ sử dụng một tên phương thức khác,
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
26 thay vì
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
27:

Phương pháp

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
28 được gọi là đầu tiên. Nó gọi
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
29 để đọc dữ liệu từ ổ cắm và lưu trữ trong bộ đệm nhận.

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6

Hãy nhớ rằng khi

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
29 được gọi, tất cả các dữ liệu tạo nên một tin nhắn hoàn chỉnh có thể chưa đến.
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
29 có thể cần được gọi lại. Đây là lý do tại sao có kiểm tra trạng thái cho từng phần của tin nhắn trước khi phương thức thích hợp để xử lý nó được gọi.

Trước khi một phương thức xử lý một phần của tin nhắn, trước tiên nó kiểm tra để đảm bảo đủ byte đã được đọc vào bộ đệm nhận. Nếu họ có, nó xử lý các byte tương ứng của nó, sẽ loại bỏ chúng khỏi bộ đệm và ghi đầu ra của nó vào một biến mà Lọ sử dụng bởi giai đoạn xử lý tiếp theo. Vì có ba thành phần cho một tin nhắn, có ba kiểm tra trạng thái và các cuộc gọi phương thức

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
32:

Thành phần tin nhắn

Phiên bản máy khách của

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18 là tương tự:

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
7

Vì máy khách bắt đầu kết nối với máy chủ và gửi yêu cầu trước, biến trạng thái

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
52 được kiểm tra. Nếu một yêu cầu đã được xếp hàng, nó sẽ gọi
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
53. Phương thức
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
54 tạo yêu cầu và ghi nó vào bộ đệm gửi. Nó cũng đặt biến trạng thái
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
52 để nó chỉ được gọi một lần.

Giống như đối với máy chủ,

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
45 gọi
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
62 nếu có dữ liệu trong bộ đệm gửi.

Sự khác biệt đáng chú ý trong phiên bản

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18 của máy khách là lần kiểm tra cuối cùng để xem liệu yêu cầu đã được xếp hàng. Điều này sẽ được giải thích nhiều hơn trong tập lệnh chính của khách hàng, nhưng lý do cho điều này là để nói với
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
08 để ngừng giám sát ổ cắm cho các sự kiện ghi. Nếu yêu cầu đã được xếp hàng và bộ đệm gửi trống, thì bạn đã viết xong và bạn chỉ quan tâm đến các sự kiện đọc. Không có lý do gì để được thông báo rằng ổ cắm có thể ghi được.

Để kết thúc phần này, hãy xem xét suy nghĩ này: Mục đích chính của phần này là giải thích rằng

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
08 đang gọi vào lớp
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 thông qua phương pháp
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13 và để mô tả cách quản lý trạng thái.

Điều này rất quan trọng vì

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13 sẽ được gọi là nhiều lần trong suốt cuộc đời của kết nối. Do đó, hãy đảm bảo rằng bất kỳ phương thức nào chỉ nên được gọi một lần đều được kiểm tra một biến trạng thái hoặc biến trạng thái được đặt theo phương thức đều được người gọi kiểm tra.

Kịch bản chính của máy chủ

Trong tập lệnh chính của máy chủ

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
91, các đối số được đọc từ dòng lệnh chỉ định giao diện và cổng để nghe:

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8

Ví dụ: để nghe trên giao diện loopback trên cổng

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
65, nhập:

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9

Sử dụng một chuỗi trống cho

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
66 để nghe trên tất cả các giao diện.

Sau khi tạo ổ cắm, một cuộc gọi được thực hiện cho

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
67 với tùy chọn
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
68:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
0

Đặt tùy chọn ổ cắm này tránh lỗi

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
69. Bạn sẽ thấy điều này khi khởi động máy chủ trên một cổng có các kết nối ở trạng thái Time_Wait.

Ví dụ: nếu máy chủ chủ động đóng kết nối, nó sẽ vẫn ở trạng thái

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
70 trong hai phút trở lên, tùy thuộc vào hệ điều hành. Nếu bạn cố gắng khởi động lại máy chủ trước khi trạng thái
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
70 hết hạn, thì bạn sẽ nhận được ngoại lệ
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
72 là
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
69. Đây là một biện pháp bảo vệ để đảm bảo rằng bất kỳ gói nào bị trì hoãn trong mạng không được cung cấp cho ứng dụng sai.

Vòng lặp sự kiện bắt gặp bất kỳ lỗi nào để máy chủ có thể ở lại và tiếp tục chạy:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
1

Khi kết nối máy khách được chấp nhận, đối tượng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 được tạo:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
2

Đối tượng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 được liên kết với ổ cắm trong cuộc gọi đến
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
04 và ban đầu được đặt để chỉ theo dõi các sự kiện đọc. Khi yêu cầu đã được đọc, bạn sẽ sửa đổi nó để chỉ nghe các sự kiện ghi.

Một lợi thế của việc thực hiện phương pháp này trong máy chủ là trong hầu hết các trường hợp, khi một ổ cắm khỏe mạnh và không có vấn đề về mạng, nó sẽ luôn có thể ghi được.

Nếu bạn đã nói với

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
04 cũng theo dõi
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
78, thì vòng lặp sự kiện sẽ ngay lập tức thức dậy và thông báo cho bạn rằng đây là trường hợp. Tuy nhiên, tại thời điểm này, không có lý do gì để thức dậy và gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 trên ổ cắm. Không có phản hồi nào để gửi, bởi vì một yêu cầu chưa được xử lý. Điều này sẽ tiêu thụ và chất thải chu kỳ CPU có giá trị.

Lớp tin nhắn máy chủ

Trong phần Nhập thông báo, bạn đã tìm hiểu cách đối tượng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 được gọi là hành động khi các sự kiện ổ cắm đã sẵn sàng thông qua
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13. Bây giờ bạn sẽ tìm hiểu những gì xảy ra khi dữ liệu được đọc trên ổ cắm và một thành phần hoặc mảnh của thông báo đã sẵn sàng để được máy chủ xử lý.

Lớp tin nhắn máy chủ có tính bằng

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
00, là một phần của mã nguồn bạn đã tải xuống trước đó. Bạn cũng có thể tải xuống mã bằng cách nhấp vào liên kết bên dưới:

Các phương thức xuất hiện trong lớp theo thứ tự mà việc xử lý diễn ra cho một tin nhắn.

Khi máy chủ đã đọc ít nhất hai byte, tiêu đề có độ dài cố định có thể được xử lý:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
3

Tiêu đề có độ dài cố định là một số nguyên 2 byte trong mạng, hoặc đơn đặt hàng Big-endian, byte. Nó chứa chiều dài của tiêu đề JSON. Bạn sẽ sử dụng struct.unpack () để đọc giá trị, giải mã nó và lưu trữ nó trong

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
34. Sau khi xử lý phần của thông báo mà nó chịu trách nhiệm,
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
84 sẽ loại bỏ nó khỏi bộ đệm nhận.

Giống như với tiêu đề có độ dài cố định, khi có đủ dữ liệu trong bộ đệm nhận để chứa tiêu đề JSON, nó cũng có thể được xử lý:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
4

Phương pháp

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
85 được gọi để giải mã và giảm giá tiêu đề JSON thành một từ điển. Bởi vì tiêu đề JSON được định nghĩa là unicode với mã hóa UTF-8,
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
86 được mã hóa cứng trong cuộc gọi. Kết quả được lưu vào
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
36. Sau khi xử lý phần của thông báo mà nó chịu trách nhiệm,
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
35 sẽ loại bỏ nó khỏi bộ đệm nhận.

Tiếp theo là nội dung thực tế, hoặc tải trọng của tin nhắn. Nó được mô tả bởi tiêu đề JSON trong

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
36. Khi
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
83 byte có sẵn trong bộ đệm nhận, yêu cầu có thể được xử lý:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
5

Sau khi lưu nội dung tin nhắn vào biến

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
07,
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
27 sẽ xóa nó khỏi bộ đệm nhận. Sau đó, nếu loại nội dung là JSON,
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
27 giải mã và giải mã nó. Nếu nó không, ứng dụng ví dụ này giả định rằng nó là một yêu cầu nhị phân và chỉ cần in loại nội dung.

Điều cuối cùng

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
27 làm là sửa đổi bộ chọn chỉ để giám sát các sự kiện ghi. Trong tập lệnh chính của máy chủ,
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
91, ổ cắm ban đầu được đặt để giám sát các sự kiện đọc. Bây giờ yêu cầu đã được xử lý đầy đủ, bạn không còn quan tâm đến việc đọc.

Một phản hồi bây giờ có thể được tạo và ghi vào ổ cắm. Khi ổ cắm có thể ghi,

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
42 được gọi từ
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
6

Một phản hồi được tạo bằng cách gọi các phương thức khác, tùy thuộc vào loại nội dung. Trong ứng dụng ví dụ này, việc tra cứu từ điển đơn giản được thực hiện cho các yêu cầu JSON khi

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
98. Đối với các ứng dụng của riêng bạn, bạn có thể xác định các phương pháp khác được gọi ở đây.

Sau khi tạo thông báo phản hồi, biến trạng thái

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
99 được đặt để
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
18 không gọi lại
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
42. Cuối cùng, phản hồi được thêm vào bộ đệm gửi. Điều này được nhìn thấy và gửi qua
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
45.

Một chút khó để tìm ra là làm thế nào để đóng kết nối sau khi phản hồi được viết. Bạn có thể thực hiện cuộc gọi đến

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 trong phương thức
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
45:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
7

Mặc dù nó hơi ẩn, nhưng đây là một sự đánh đổi có thể chấp nhận được khi lớp

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 chỉ xử lý một tin nhắn trên mỗi kết nối. Sau khi phản hồi được viết, không còn gì để máy chủ làm. Nó đã hoàn thành công việc của mình.

Tập lệnh chính của khách hàng

Trong tập lệnh chính của máy khách,

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
90, các đối số được đọc từ dòng lệnh và được sử dụng để tạo yêu cầu và khởi động kết nối với máy chủ:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
8

Đây là một ví dụ:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
9

Sau khi tạo một từ điển đại diện cho yêu cầu từ các đối số dòng lệnh, máy chủ, cổng và từ điển yêu cầu được chuyển đến

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
07:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
0

Một ổ cắm được tạo cho kết nối máy chủ, cũng như đối tượng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 bằng từ điển
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
41.

Giống như đối với máy chủ, đối tượng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 được liên kết với ổ cắm trong cuộc gọi đến
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
04. Tuy nhiên, đối với máy khách, ổ cắm ban đầu được thiết lập để được theo dõi cho cả các sự kiện đọc và viết. Khi yêu cầu đã được viết, bạn sẽ sửa đổi nó để chỉ nghe các sự kiện đọc.

Cách tiếp cận này mang lại cho bạn lợi thế tương tự như máy chủ: không lãng phí chu kỳ CPU. Sau khi yêu cầu đã được gửi, bạn không còn quan tâm đến các sự kiện viết, vì vậy, không có lý do gì để thức dậy và xử lý chúng.

Lớp tin nhắn khách hàng

Trong phần Nhập thông báo, bạn đã tìm hiểu làm thế nào đối tượng tin nhắn được gọi là hành động khi các sự kiện ổ cắm đã sẵn sàng thông qua

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
13. Bây giờ bạn sẽ tìm hiểu những gì xảy ra sau khi dữ liệu được đọc và ghi trên ổ cắm và một thông báo đã sẵn sàng để được xử lý bởi máy khách.

Lớp tin nhắn của máy khách nằm trong

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
03, là một phần của mã nguồn bạn đã tải xuống trước đó. Bạn cũng có thể tải xuống mã bằng cách nhấp vào liên kết bên dưới:

Các phương thức xuất hiện trong lớp theo thứ tự mà việc xử lý diễn ra cho một tin nhắn.

Nhiệm vụ đầu tiên cho khách hàng là xếp hàng yêu cầu:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
1

Các từ điển được sử dụng để tạo yêu cầu, tùy thuộc vào những gì được truyền trên dòng lệnh, nằm trong tập lệnh chính của máy khách,

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
90. Từ điển yêu cầu được truyền như một đối số cho lớp khi một đối tượng
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86 được tạo.

Thông báo yêu cầu được tạo và thêm vào bộ đệm gửi, sau đó được nhìn thấy và gửi qua

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
45. Biến trạng thái
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
17 được đặt sao cho
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
53 được gọi lại.

Sau khi yêu cầu đã được gửi, máy khách chờ phản hồi từ máy chủ.

Các phương thức đọc và xử lý một thông báo trong máy khách giống như đối với máy chủ. Vì dữ liệu phản hồi được đọc từ ổ cắm, các phương thức tiêu đề

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
32 được gọi là:
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
84 và
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
21.

Sự khác biệt là trong việc đặt tên của các phương pháp

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
32 cuối cùng và thực tế là họ xử lý một phản hồi, không tạo ra một:
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
26,
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
24 và
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
25.

Cuối cùng, nhưng chắc chắn không kém phần quan trọng, là cuộc gọi cuối cùng cho

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
26:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
2

Lớp thông báo kết thúc

Để kết thúc việc học của bạn về lớp

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
86, điều đáng nói là một vài điều quan trọng cần chú ý với một vài phương pháp hỗ trợ.

Bất kỳ trường hợp ngoại lệ nào được đưa ra bởi lớp đều bị bắt bởi tập lệnh chính trong Điều khoản

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
28 bên trong vòng lặp sự kiện:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
3

Lưu ý dòng:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
29.

Đây là một dòng thực sự quan trọng, vì nhiều lý do! Nó không chỉ đảm bảo rằng ổ cắm được đóng, mà

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
29 cũng loại bỏ ổ cắm khỏi được theo dõi bởi
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90. Điều này đơn giản hóa rất nhiều mã trong lớp và giảm độ phức tạp. Nếu có một ngoại lệ hoặc bạn tự nâng cao một cách rõ ràng, bạn sẽ biết
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 sẽ chăm sóc việc dọn dẹp.

Các phương pháp

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
33 và
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
34 cũng chứa một cái gì đó thú vị:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
4

Lưu ý dòng

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
35.

Phương pháp

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
45 cũng có một. Những dòng này rất quan trọng vì chúng bắt được một lỗi tạm thời và bỏ qua nó bằng
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
37. Lỗi tạm thời là khi ổ cắm sẽ chặn, ví dụ nếu nó chờ đợi trên mạng hoặc đầu kia của kết nối, còn được gọi là ngang hàng của nó.

Bằng cách bắt và bỏ qua ngoại lệ với

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
37,
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
90 cuối cùng sẽ kích hoạt một cuộc gọi mới và bạn sẽ có một cơ hội khác để đọc hoặc viết dữ liệu.

Chạy máy khách và máy chủ ứng dụng

Sau tất cả những công việc khó khăn này, đó là thời gian để có một số niềm vui và chạy một số tìm kiếm!

Trong các ví dụ này, bạn sẽ chạy máy chủ để nó lắng nghe trên tất cả các giao diện bằng cách chuyển một chuỗi trống cho đối số

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
00. Điều này sẽ cho phép bạn chạy máy khách và kết nối từ một máy ảo mà trên mạng khác. Nó mô phỏng một máy PowerPC lớn.

Đầu tiên, khởi động máy chủ:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
5

Bây giờ chạy máy khách và nhập tìm kiếm. Xem nếu bạn có thể tìm thấy anh ấy:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
6

Bạn có thể nhận thấy rằng thiết bị đầu cuối đang chạy một shell mà sử dụng mã hóa văn bản của Unicode (UTF-8), do đó, đầu ra trên in độc đáo với biểu tượng cảm xúc.

Bây giờ xem bạn có thể tìm thấy những chú chó con không:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
7

Lưu ý chuỗi byte được gửi qua mạng cho yêu cầu trong dòng

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
41. Nó dễ dàng hơn để xem nếu bạn tìm kiếm các byte được in bằng hex đại diện cho biểu tượng cảm xúc chó con:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
42. Nếu thiết bị đầu cuối của bạn đang sử dụng Unicode với UTF-8 mã hóa, bạn sẽ có thể nhập biểu tượng cảm xúc để tìm kiếm.

Điều này chứng tỏ rằng bạn đã gửi các byte thô qua mạng và chúng cần được giải mã bởi người nhận để được giải thích chính xác. Đây là lý do tại sao bạn đã đi đến tất cả những rắc rối để tạo một tiêu đề chứa loại nội dung và mã hóa.

Ở đây, đầu ra máy chủ từ cả hai kết nối máy khách ở trên:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
8

Nhìn vào dòng

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
41 để xem các byte được ghi vào ổ cắm của máy khách. Đây là thông báo phản hồi của máy chủ.

Bạn cũng có thể kiểm tra gửi các yêu cầu nhị phân đến máy chủ nếu đối số

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
44 là bất cứ điều gì khác ngoài
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
45:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
9

Bởi vì yêu cầu

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
46 không phải là
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
47, máy chủ coi nó là một loại nhị phân tùy chỉnh và không thực hiện giải mã JSON. Nó chỉ đơn giản là in
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
46 và trả về mười byte đầu tiên cho máy khách:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
0

Xử lý sự cố

Chắc chắn, một cái gì đó đã giành được công việc, và bạn sẽ tự hỏi phải làm gì. Đừng lo lắng, nó xảy ra với tất cả mọi người. Hy vọng rằng, với sự giúp đỡ của hướng dẫn này, trình gỡ lỗi của bạn và công cụ tìm kiếm yêu thích của bạn, bạn sẽ có thể đi lại với phần mã nguồn.

Nếu không, điểm dừng đầu tiên của bạn phải là tài liệu mô -đun ổ cắm Python. Hãy chắc chắn rằng bạn đọc tất cả các tài liệu cho từng hàm hoặc phương thức mà bạn gọi. Ngoài ra, đọc qua phần tham chiếu dưới đây cho các ý tưởng. Đặc biệt, kiểm tra phần lỗi.

Đôi khi, nó không phải là tất cả về mã nguồn. Mã nguồn có thể chính xác và nó chỉ là máy chủ khác, máy khách hoặc máy chủ. Hoặc nó có thể là mạng. Có thể một bộ định tuyến, tường lửa hoặc một số thiết bị mạng khác đang chơi người đàn ông.

Đối với các loại vấn đề này, các công cụ bổ sung là rất cần thiết. Dưới đây là một vài công cụ và tiện ích có thể giúp hoặc ít nhất là cung cấp một số manh mối.

Ping

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
49 sẽ kiểm tra xem máy chủ có còn sống và kết nối với mạng hay không bằng cách gửi yêu cầu Echo ICMP. Nó giao tiếp trực tiếp với ngăn xếp giao thức TCP/IP của hệ điều hành, do đó, nó hoạt động độc lập với bất kỳ ứng dụng nào chạy trên máy chủ.

Dưới đây là một ví dụ về việc chạy ping trên macOS:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
1

Lưu ý các số liệu thống kê ở cuối đầu ra. Điều này có thể hữu ích khi bạn đang cố gắng khám phá các vấn đề kết nối không liên tục. Ví dụ, có mất gói nào không? Có bao nhiêu độ trễ? Bạn có thể kiểm tra thời gian khứ hồi.

Nếu có một tường lửa giữa bạn và máy chủ khác, một yêu cầu Echo Ping có thể không được phép. Một số quản trị viên tường lửa thực hiện các chính sách thực thi điều này. Ý tưởng là họ không muốn chủ nhà của họ có thể phát hiện được. Nếu đây là trường hợp và bạn có các quy tắc tường lửa được thêm vào để cho phép các máy chủ giao tiếp, thì hãy đảm bảo rằng các quy tắc cũng cho phép ICMP vượt qua giữa chúng.

ICMP là giao thức được sử dụng bởi

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
49, nhưng nó cũng là giao thức TCP và các giao thức cấp thấp khác sử dụng để truyền đạt các thông báo lỗi. Nếu bạn trải nghiệm hành vi kỳ lạ hoặc kết nối chậm, đây có thể là lý do.

Tin nhắn ICMP được xác định theo loại và mã. Để cung cấp cho bạn một ý tưởng về thông tin quan trọng mà họ mang theo, đây là một số ít:

Loại ICMPMã ICMPSự mô tả
8 0 Yêu cầu echo
0 0 Echo trả lời
3 0 Mạng đích không thể truy cập được
3 1 Máy chủ đích không thể truy cập được
3 2 Giao thức đích không thể truy cập được
3 3 Cổng đích không thể truy cập được
3 4 Yêu cầu phân mảnh và bộ cờ DF
11 0 TTL đã hết hạn trong quá trình vận chuyển

Xem bài viết MTU Discovery để biết thông tin liên quan đến phân mảnh và tin nhắn ICMP. Đây là một ví dụ về một cái gì đó có thể gây ra hành vi kỳ lạ.

netstat

Trong phần xem trạng thái ổ cắm, bạn đã tìm hiểu cách

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
39 có thể được sử dụng để hiển thị thông tin về ổ cắm và trạng thái hiện tại của chúng. Tiện ích này có sẵn trên MacOS, Linux và Windows.

Phần đó đã không đề cập đến các cột

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
52 và
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
53 trong đầu ra ví dụ. Các cột này sẽ cho bạn thấy số lượng byte được giữ trong bộ đệm mạng được xếp hàng để truyền hoặc nhận, nhưng vì một số lý do, thiên đường đã được đọc hoặc viết bởi ứng dụng từ xa hoặc cục bộ.

Nói cách khác, các byte đang chờ đợi trong bộ đệm mạng trong hàng đợi hệ điều hành. Một lý do có thể là ứng dụng bị ràng buộc CPU hoặc không thể gọi

# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
29 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
62 và xử lý các byte. Hoặc có thể có các vấn đề mạng ảnh hưởng đến truyền thông, như tắc nghẽn hoặc phần cứng mạng bị hỏng hoặc cáp.

Để chứng minh điều này và xem bạn có thể gửi bao nhiêu dữ liệu trước khi thấy lỗi, bạn có thể thử máy khách thử nghiệm kết nối với máy chủ thử nghiệm và liên tục gọi

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
62. Máy chủ thử nghiệm không bao giờ gọi
# echo-server.py

import socket

HOST = "127.0.0.1"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
29. Nó chỉ chấp nhận kết nối. Điều này khiến các bộ đệm mạng trên máy chủ điền, cuối cùng làm tăng lỗi trên máy khách.

Đầu tiên, khởi động máy chủ:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
2

Sau đó, chạy máy khách để xem lỗi là gì:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
3

Tại đây, ____ ____139 đầu ra từ trong khi máy khách và máy chủ vẫn đang chạy, với máy khách in thông báo lỗi trên nhiều lần:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
4

Mục đầu tiên là máy chủ (

import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
40 có cổng 65432):

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
5

Lưu ý

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
52:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
61.

Mục thứ hai là máy khách (

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
62 có cổng 65432):

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
6

Lưu ý

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
53:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
64.

Khách hàng chắc chắn đang cố gắng viết byte, nhưng máy chủ không phải là đọc chúng. Điều này đã khiến hàng đợi bộ đệm mạng máy chủ điền vào phía nhận và hàng đợi bộ đệm mạng của máy khách để điền vào phía gửi.

các cửa sổ

Nếu bạn làm việc với Windows, có một bộ tiện ích mà bạn chắc chắn nên kiểm tra xem bạn có chưa sử dụng được không: Windows SysiNternals.

Một trong số đó là

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
65. TCPVIEW là một đồ họa
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
39 cho Windows. Ngoài địa chỉ, số cổng và trạng thái ổ cắm, nó sẽ cho bạn thấy bạn chạy tổng số cho số lượng gói và byte được gửi và nhận. Giống như với tiện ích UNIX
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
57, bạn cũng nhận được tên quy trình và ID. Kiểm tra các menu cho các tùy chọn hiển thị khác.

Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng

WIRESHARK

Đôi khi bạn cần phải xem những gì xảy ra trên dây. Quên về những gì nhật ký ứng dụng nói hoặc giá trị là gì mà được trả lại từ một cuộc gọi thư viện. Bạn muốn xem những gì thực sự được gửi hoặc nhận trên mạng. Cũng giống như với những người gỡ lỗi, khi bạn cần nhìn thấy nó, không có sự thay thế nào.

Wireshark là một máy phân tích giao thức mạng và ứng dụng thu thập lưu lượng chạy trên macOS, Linux và Windows, trong số các phân tích khác. Có một phiên bản GUI có tên

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
68 và cũng là một phiên bản dựa trên văn bản, có tên là
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
69.

Chạy thu thập lưu lượng truy cập là một cách tuyệt vời để xem cách ứng dụng hoạt động trên mạng và thu thập bằng chứng về những gì nó gửi và nhận, và tần suất và bao nhiêu. Bạn cũng có thể thấy khi khách hoặc máy chủ đóng hoặc hủy bỏ kết nối hoặc ngừng phản hồi. Thông tin này có thể cực kỳ hữu ích khi bạn xử lý sự cố.

Có nhiều hướng dẫn tốt và các tài nguyên khác trên web sẽ hướng dẫn bạn những điều cơ bản của việc sử dụng Wireshark và Tshark.

Dưới đây, một ví dụ về việc bắt giữ lưu lượng truy cập bằng cách sử dụng Wireshark trên giao diện Loopback:

Hướng dẫn client to client communication python - Python giao tiếp giữa khách hàng với khách hàng

Ở đây, ví dụ tương tự được hiển thị ở trên bằng cách sử dụng

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
69:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
7

Tiếp theo, bạn sẽ nhận được nhiều tài liệu tham khảo hơn để hỗ trợ hành trình lập trình ổ cắm của bạn!

Tài liệu tham khảo

Bạn có thể sử dụng phần này làm tài liệu tham khảo chung với thông tin bổ sung và liên kết đến các tài nguyên bên ngoài.

Tài liệu Python

  • Mô -đun ổ cắm Python
  • Lập trình ổ cắm Python từ

Lỗi

Sau đây là từ tài liệu mô -đun Python từ

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
71:

Tất cả các lỗi đều tăng ngoại lệ. Các ngoại lệ bình thường cho các loại đối số không hợp lệ và các điều kiện ngoài bộ nhớ có thể được nêu ra; Bắt đầu từ Python 3.3, các lỗi liên quan đến ổ cắm hoặc ngữ nghĩa địa chỉ tăng

import socket

host = '192.168.43.209'  # Standard loopback interface address 
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 2 :  ")
72 hoặc một trong các lớp con của nó. (Nguồn)

Dưới đây là một số lỗi phổ biến mà bạn có thể gặp phải khi làm việc với ổ cắm:

Ngoại lệ
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
73 hằng số
Sự mô tả
ChặnEwouldblockTài nguyên tạm thời không có. Ví dụ: ở chế độ không chặn, khi gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 và đồng đẳng đang bận và không đọc, hàng đợi (bộ đệm mạng) đã đầy. Hoặc có vấn đề với mạng. Hy vọng rằng đây là một điều kiện tạm thời.
OserrorEaddrinuseĐịa chỉ đã được sử dụng. Đảm bảo rằng có một quy trình khác không chạy mà sử dụng cùng một số cổng và máy chủ của bạn đang đặt tùy chọn ổ cắm
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
75:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
76.
ConnectionResetErrorEconnresetĐặt lại kết nối theo ngang hàng. Quá trình từ xa bị sập hoặc không đóng ổ cắm đúng cách, còn được gọi là tắt máy ô uế. Hoặc có một tường lửa hoặc thiết bị khác trong đường dẫn mạng mà thiếu các quy tắc hoặc hành vi sai.
TimeouterrorEtimedoutChiến dịch kết thúc. Không có phản hồi từ ngang hàng.
ConnectionRefuseRorrorEconnref sử dụngKết nối từ chối. Không nghe ứng dụng trên cổng được chỉ định.

Ổ cắm địa chỉ gia đình

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 và
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
78 đại diện cho các họ địa chỉ và giao thức được sử dụng cho đối số đầu tiên đến
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9. API sử dụng một địa chỉ mong đợi nó ở một định dạng nhất định, tùy thuộc vào việc ổ cắm được tạo bằng
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 hay
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
78.

Địa chỉ gia đìnhGiao thứcĐịa chỉ tupleSự mô tả
ChặnEwouldblockTài nguyên tạm thời không có. Ví dụ: ở chế độ không chặn, khi gọi
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
6 và đồng đẳng đang bận và không đọc, hàng đợi (bộ đệm mạng) đã đầy. Hoặc có vấn đề với mạng. Hy vọng rằng đây là một điều kiện tạm thời.
Oserror
EaddrinuseĐịa chỉ đã được sử dụng. Đảm bảo rằng có một quy trình khác không chạy mà sử dụng cùng một số cổng và máy chủ của bạn đang đặt tùy chọn ổ cắm
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
75:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
76.
ConnectionResetErrorEconnreset

Đặt lại kết nối theo ngang hàng. Quá trình từ xa bị sập hoặc không đóng ổ cắm đúng cách, còn được gọi là tắt máy ô uế. Hoặc có một tường lửa hoặc thiết bị khác trong đường dẫn mạng mà thiếu các quy tắc hoặc hành vi sai.

Timeouterror

Etimedout

Chiến dịch kết thúc. Không có phản hồi từ ngang hàng.

ConnectionRefuseRorror

Econnref sử dụng

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
8

Kết nối từ chối. Không nghe ứng dụng trên cổng được chỉ định.

Ổ cắm địa chỉ gia đình

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 và
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
78 đại diện cho các họ địa chỉ và giao thức được sử dụng cho đối số đầu tiên đến
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
9. API sử dụng một địa chỉ mong đợi nó ở một định dạng nhất định, tùy thuộc vào việc ổ cắm được tạo bằng
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
8 hay
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
78.

Sau đây là từ tài liệu mô -đun Python từ

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
71:

Địa chỉ gia đình

Giao thức

Ví dụ: trên Linux, xem

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
16, tệp cấu hình chuyển đổi dịch vụ tên. Một nơi khác để kiểm tra MacOS và Linux là tệp
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
17. Trên Windows, xem
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
18. Tệp
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
19 chứa một bảng tĩnh của ánh xạ tên-địa chỉ ở định dạng văn bản đơn giản. DNS là một phần khác của câu đố hoàn toàn.

Điều thú vị là, tính đến tháng 6 năm 2018, có một bản nháp của RFC cho phép ‘Localhost, được địa phương thảo luận về các công ước, giả định và bảo mật xung quanh việc sử dụng tên là Local Localhost.

Điều quan trọng để hiểu là khi bạn sử dụng tên máy chủ trong ứng dụng của mình, các địa chỉ được trả lại theo nghĩa đen có thể là bất cứ điều gì. Don Tiết đưa ra các giả định liên quan đến một tên nếu bạn có một ứng dụng nhạy cảm với bảo mật. Tùy thuộc vào ứng dụng và môi trường của bạn, điều này có thể hoặc không phải là mối quan tâm đối với bạn.

Bất kể bạn có sử dụng tên máy chủ hay không, nếu ứng dụng của bạn cần hỗ trợ các kết nối an toàn thông qua mã hóa và xác thực, thì bạn có thể muốn xem xét sử dụng TLS. Đây là chủ đề riêng của nó và ngoài phạm vi của hướng dẫn này. Xem tài liệu mô -đun SSL Python sườn để bắt đầu. Đây là cùng một giao thức mà trình duyệt web của bạn sử dụng để kết nối an toàn với các trang web.

Với giao diện, địa chỉ IP và độ phân giải tên để xem xét, có nhiều biến. Những gì bạn nên làm? Dưới đây là một số khuyến nghị mà bạn có thể sử dụng nếu bạn không có quy trình xem xét ứng dụng mạng:

Đăng kíCách sử dụngsự giới thiệu
Người phục vụGiao diện LoopbackSử dụng địa chỉ IP, chẳng hạn như
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71.
Người phục vụGiao diện LoopbackSử dụng địa chỉ IP, chẳng hạn như
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71.
Giao diện EthernetGiao diện LoopbackSử dụng địa chỉ IP, chẳng hạn như
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71.
Giao diện EthernetGiao diện LoopbackSử dụng địa chỉ IP, chẳng hạn như
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
02 hoặc
import socket

host = '192.168.43.209'  # Standard loopback interface address         
(localhost)
port = 65432        # Port to listen on (non-privileged ports are > 1023)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))



from_server = client.recv(4096)
print (from_server)
client.send(b"I am client 1 :  ")
71.

Giao diện Ethernet

Sử dụng một địa chỉ IP, chẳng hạn như import socket host = '192.168.43.209' # Standard loopback interface address (localhost) port = 65432 # Port to listen on (non-privileged ports are > 1023) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((host, port)) from_server = client.recv(4096) print (from_server) client.send(b"I am client 1 : ") 09. Để hỗ trợ nhiều giao diện, hãy sử dụng một chuỗi trống cho tất cả các giao diện/địa chỉ. Xem ghi chú bảo mật ở trên.

Khách hàng

Sử dụng địa chỉ IP để thống nhất và không phụ thuộc vào độ phân giải tên. Đối với trường hợp điển hình, sử dụng tên máy chủ. Xem ghi chú bảo mật ở trên.

Đối với máy khách hoặc máy chủ, nếu bạn cần xác thực máy chủ mà bạn đang kết nối, hãy xem xét sử dụng TLS.

Chặn các cuộc gọi

Một hàm hoặc phương thức tạm thời tạm dừng ứng dụng của bạn là một cuộc gọi chặn. Ví dụ, # echo-server.py # ... with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break conn.sendall(data) 3, # echo-server.py # ... with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break conn.sendall(data) 4, # echo-server.py # ... with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break conn.sendall(data) 6 và # echo-server.py # ... with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break conn.sendall(data) 7, có nghĩa là họ không trả lại ngay lập tức. Chặn các cuộc gọi phải chờ trên các cuộc gọi hệ thống (I/O) để hoàn thành trước khi chúng có thể trả về một giá trị. Vì vậy, bạn, người gọi, bị chặn cho đến khi họ đã hoàn thành hoặc thời gian chờ hoặc lỗi khác xảy ra.

Chặn các cuộc gọi ổ cắm có thể được đặt thành chế độ không chặn để chúng quay lại ngay lập tức. Nếu bạn làm điều này, thì bạn sẽ cần ít nhất phải tái cấu trúc hoặc thiết kế lại ứng dụng của mình để xử lý thao tác ổ cắm khi nó sẵn sàng.

Bởi vì cuộc gọi trả về ngay lập tức, dữ liệu có thể chưa sẵn sàng. Callee đang chờ đợi trên mạng và đã có thời gian để hoàn thành công việc của mình. Nếu đây là trường hợp, thì trạng thái hiện tại là giá trị

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    pass  # Use the socket object without calling s.close().
73
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
30. Chế độ không chặn được hỗ trợ với .setblocking ().

Theo mặc định, ổ cắm luôn được tạo ở chế độ chặn. Xem ghi chú về thời gian chờ ổ cắm để biết mô tả của ba chế độ.

Đóng kết nối

Một điều thú vị cần lưu ý với TCP là nó hoàn toàn hợp pháp cho máy khách hoặc máy chủ để đóng phía kết nối của họ trong khi phía bên kia vẫn mở. Điều này được gọi là kết nối nửa mở của người Viking. Nó đưa ra quyết định của ứng dụng cho dù điều này có mong muốn hay không. Nói chung, nó không. Ở trạng thái này, phía đã đóng phần cuối của kết nối không còn có thể gửi dữ liệu. Họ chỉ có thể nhận được nó.

Thứ tự byte cũng rất quan trọng đối với các chuỗi văn bản được biểu diễn dưới dạng các chuỗi đa byte, như Unicode. Trừ khi bạn luôn luôn sử dụng ASCII thực sự, nghiêm ngặt và kiểm soát việc triển khai máy khách và máy chủ, bạn có thể nên sử dụng Unicode với mã hóa như UTF-8 hoặc một bản hỗ trợ Dấu thứ tự byte (BOM).

Nó rất quan trọng để xác định rõ ràng việc mã hóa được sử dụng trong giao thức lớp ứng dụng của bạn. Bạn có thể làm điều này bằng cách bắt buộc tất cả văn bản là UTF-8 hoặc sử dụng tiêu đề mã hóa nội dung trực tuyến chỉ định mã hóa. Điều này ngăn ứng dụng của bạn không phải phát hiện mã hóa mà bạn nên tránh nếu có thể.

Điều này trở nên có vấn đề khi có dữ liệu liên quan đến việc lưu trữ trong các tệp hoặc cơ sở dữ liệu và ở đó, không có siêu dữ liệu nào có sẵn chỉ định mã hóa của nó. Khi dữ liệu được chuyển sang điểm cuối khác, nó sẽ phải cố gắng phát hiện mã hóa. Để thảo luận, xem bài viết của Wikipedia, Unicode, trong đó tham chiếu RFC 3629: UTF-8, định dạng chuyển đổi của ISO 10646:

Tuy nhiên, RFC 3629, tiêu chuẩn UTF-8, khuyến nghị rằng các dấu lệnh byte bị cấm trong các giao thức sử dụng UTF-8, nhưng thảo luận về các trường hợp có thể không thể thực hiện được. Ngoài ra, hạn chế lớn đối với các mẫu có thể có trong UTF-8 (ví dụ: không thể có bất kỳ byte đơn độc nào có bộ bit cao) có nghĩa là có thể phân biệt UTF-8 với các mã hóa ký tự khác mà không cần dựa vào BOM. (Nguồn)

Việc thực hiện từ đây là luôn luôn lưu trữ mã hóa được sử dụng cho dữ liệu mà xử lý bởi ứng dụng của bạn nếu nó có thể thay đổi. Nói cách khác, hãy cố gắng bằng cách nào đó lưu trữ mã hóa dưới dạng siêu dữ liệu nếu nó không phải lúc nào cũng UTF-8 hoặc một số mã hóa khác với BOM. Sau đó, bạn có thể gửi mã hóa đó trong một tiêu đề cùng với dữ liệu để cho người nhận biết nó là gì.

Đặt hàng byte được sử dụng trong TCP/IP là Big-Endian và được gọi là thứ tự mạng. Thứ tự mạng được sử dụng để biểu diễn số nguyên trong các lớp thấp hơn của ngăn xếp giao thức, như địa chỉ IP và số cổng. Mô -đun ổ cắm Python Python bao gồm các chức năng chuyển đổi số nguyên thành và từ mạng và đơn đặt hàng byte:

Hàm sốSự mô tả
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
31
Chuyển đổi số nguyên dương 32 bit từ mạng sang thứ tự byte. Trên các máy nơi đơn đặt hàng byte máy chủ giống như thứ tự byte mạng, đây là không có op; Nếu không, nó thực hiện hoạt động hoán đổi 4 byte.
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
32
Chuyển đổi số nguyên dương 16 bit từ mạng sang đơn đặt hàng byte. Trên các máy nơi đơn đặt hàng byte máy chủ giống như thứ tự byte mạng, đây là không có op; Nếu không, nó thực hiện hoạt động hoán đổi 2 byte.
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
33
Chuyển đổi số nguyên dương 32 bit từ máy chủ sang đơn đặt hàng byte. Trên các máy nơi đơn đặt hàng byte máy chủ giống như thứ tự byte mạng, đây là không có op; Nếu không, nó thực hiện hoạt động hoán đổi 4 byte.
# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    # ...
34
Chuyển đổi số nguyên dương 16 bit từ máy chủ sang đơn đặt hàng byte. Trên các máy nơi đơn đặt hàng byte máy chủ giống như thứ tự byte mạng, đây là không có op; Nếu không, nó thực hiện hoạt động hoán đổi 2 byte.

Bạn cũng có thể sử dụng mô -đun struct để đóng gói và giải nén dữ liệu nhị phân bằng các chuỗi định dạng:

# echo-server.py

# ...

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    # ...
9

Sự kết luận

Bạn đã đề cập rất nhiều nền tảng trong hướng dẫn này! Mạng và ổ cắm là những chủ đề lớn. Nếu bạn mới sử dụng mạng hoặc ổ cắm, thì hãy không được khuyến khích bởi tất cả các thuật ngữ và từ viết tắt.

Có rất nhiều phần để làm quen với để hiểu cách mọi thứ hoạt động cùng nhau. Tuy nhiên, giống như Python, nó sẽ bắt đầu có ý nghĩa hơn khi bạn biết các mảnh riêng lẻ và dành nhiều thời gian hơn với chúng.

Trong hướng dẫn này, bạn:

  • Nhìn vào API ổ cắm cấp thấp trong mô-đun Python từ
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        pass  # Use the socket object without calling s.close().
    
    71 và thấy cách nó có thể được sử dụng để tạo các ứng dụng máy khách-máy kháchlow-level socket API in Python’s
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        pass  # Use the socket object without calling s.close().
    
    71 module and saw how it can be used to create client-server applications
  • Được xây dựng một máy khách và máy chủ có thể xử lý nhiều kết nối bằng cách sử dụng đối tượng
    # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        # ...
    
    36multiple connections using a
    # echo-server.py
    
    # ...
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        # ...
    
    36 object
  • Đã tạo lớp tùy chỉnh của riêng bạn và sử dụng nó như một giao thức lớp ứng dụng để trao đổi tin nhắn và dữ liệu giữa các điểm cuốicustom class and used it as an application-layer protocol to exchange messages and data between endpoints

Từ đây, bạn có thể sử dụng lớp tùy chỉnh của mình và xây dựng nó để tìm hiểu và giúp tạo ra các ứng dụng ổ cắm của riêng bạn dễ dàng và nhanh hơn.

Để xem lại các ví dụ, bạn có thể nhấp vào liên kết bên dưới:

Chúc mừng bạn đã đến cùng! Bây giờ bạn đang trên đường sử dụng ổ cắm trong các ứng dụng của riêng bạn. Chúc may mắn trên hành trình phát triển ổ cắm của bạn.

Làm thế nào để bạn gửi dữ liệu cho một khách hàng cụ thể trong Python?

Để gửi dữ liệu đến một máy khách cụ thể, chỉ cần gọi phương thức .Sendall (...) (thông tin thêm ở đây) của đối tượng ổ cắm máy khách cụ thể.call the . sendall(...) method (more info here) of the specific client socket object.

Làm cách nào để gửi tin nhắn từ máy chủ đến máy khách trong Python?

Làm thế nào để bạn gửi tin nhắn cho khách hàng từ một máy chủ trong Python ?..
Nhập ổ cắm ..
Nhập SYS ..
Host = ''.
Cổng = 9000 ..
s = ổ cắm.Ổ cắm (ổ cắm. AF_Inet, ổ cắm. Sock_Stream).
In 'Ổ cắm được tạo'.
S.BIND ((máy chủ, cổng)).

TCP và UDP trong Python là gì?

Giao thức Datagram người dùng (UDP) hoạt động khác với TCP/IP.Trong đó TCP là một giao thức định hướng luồng, đảm bảo rằng tất cả các dữ liệu được truyền theo đúng thứ tự, UDP là một giao thức định hướng thông báo.UDP không yêu cầu kết nối lâu dài, vì vậy việc thiết lập ổ cắm UDP đơn giản hơn một chút.TCP is a stream oriented protocol, ensuring that all of the data is transmitted in the right order, UDP is a message oriented protocol. UDP does not require a long-lived connection, so setting up a UDP socket is a little simpler.

Làm cách nào để tạo một máy khách TCP trong Python?

Nó bắt đầu bằng cách tạo ổ cắm TCP/IP ...
Nhập ổ cắm nhập SYS # Tạo Socket TCP/IP Socket = Ổ cắm.Ổ cắm (ổ cắm. ....
# Liên kết ổ cắm với port server_address = ('localhost', 10000) in >> sys.Stderr, 'Khởi động trên %s Port %s' %server_address Sock.....
# Lắng nghe cho kết nối kết nối với tất ..