Hướng dẫn how does python connect with http socket? - python kết nối với http socket như thế nào?

Tác giả

Gordon McMillan

trừu tượng

Ổ cắm được sử dụng gần như ở mọi nơi, nhưng là một trong những công nghệ bị hiểu lầm nghiêm trọng nhất xung quanh. Đây là tổng quan 10.000 feet của ổ cắm. Nó không thực sự là một hướng dẫn - bạn vẫn còn phải làm việc trong việc hoạt động. Nó không bao gồm các điểm tốt (và có rất nhiều trong số chúng), nhưng tôi hy vọng nó sẽ cung cấp cho bạn đủ nền để bắt đầu sử dụng chúng một cách khá.

Ổ cắm¶

Tôi chỉ nói về ổ cắm Inet (tức là IPv4), nhưng chúng chiếm ít nhất 99% ổ cắm được sử dụng. Và tôi sẽ chỉ nói về luồng luồng (tức là TCP) còn gì nữa không. Tôi sẽ cố gắng làm sáng tỏ bí ẩn về một ổ cắm là gì, cũng như một số gợi ý về cách làm việc với các ổ cắm chặn và không chặn. Nhưng tôi sẽ bắt đầu bằng cách nói về việc chặn ổ cắm. Bạn cần phải biết cách họ làm việc trước khi xử lý các ổ cắm không chặn.

Một phần của rắc rối với việc hiểu những điều này là ổ cắm có thể có nghĩa là một số thứ khác nhau một cách tinh tế, tùy thuộc vào ngữ cảnh. Vì vậy, trước tiên, hãy để một sự khác biệt giữa một ổ cắm ứng dụng khách của máy khách - một điểm cuối của một cuộc trò chuyện và một ổ cắm máy chủ của máy chủ, giống như một toán tử chuyển mạch. Ví dụ, ứng dụng máy khách (ví dụ, trình duyệt của bạn) sử dụng ổ cắm máy khách của máy khách; Máy chủ web mà nó nói chuyện với việc sử dụng cả ổ cắm máy chủ của máy chủ và máy khách của máy khách.

Lịch sử¶

Trong số các hình thức IPC khác nhau, các ổ cắm cho đến nay là phổ biến nhất. Trên bất kỳ nền tảng nào, có khả năng có các hình thức IPC khác nhanh hơn, nhưng đối với giao tiếp đa nền tảng, các ổ cắm là về trò chơi duy nhất trong thị trấn.

Chúng được phát minh ở Berkeley như là một phần của hương vị BSD của Unix. Chúng lan truyền như cháy rừng với internet. Với lý do chính đáng - sự kết hợp của các ổ cắm với Inet làm cho việc nói chuyện với các máy độc đoán trên khắp thế giới dễ dàng không thể tin được (ít nhất là so với các kế hoạch khác).

Tạo ổ cắm

Nói một cách thô bạo, khi bạn nhấp vào liên kết đưa bạn đến trang này, trình duyệt của bạn đã làm một cái gì đó như sau:

# create an INET, STREAMing socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# now connect to the web server on port 80 - the normal http port
s.connect(("www.python.org", 80))

Khi connect hoàn thành, ổ cắm s có thể được sử dụng để gửi yêu cầu cho văn bản của trang. Cùng một ổ cắm sẽ đọc câu trả lời, và sau đó bị phá hủy. Đúng vậy, bị phá hủy. Các ổ cắm của máy khách thường chỉ được sử dụng cho một trao đổi (hoặc một bộ trao đổi tuần tự nhỏ).

Những gì xảy ra trong máy chủ web phức tạp hơn một chút. Đầu tiên, máy chủ web tạo ra một ổ cắm máy chủ trên mạng:

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)

Một vài điều cần chú ý: Chúng tôi đã sử dụng socket.gethostname() để có thể nhìn thấy ổ cắm cho thế giới bên ngoài. Nếu chúng tôi đã sử dụng s.bind(('localhost', 80)) hoặc s.bind(('127.0.0.1', 80)), chúng tôi vẫn sẽ có một ổ cắm máy chủ trên máy chủ, nhưng một máy chủ chỉ hiển thị trong cùng một máy.

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
0 Chỉ định rằng ổ cắm có thể truy cập được bởi bất kỳ địa chỉ nào mà máy xảy ra.

Một điều thứ hai cần lưu ý: Các cổng số thấp thường được dành riêng cho các dịch vụ nổi tiếng của các dịch vụ (HTTP, SNMP, v.v.). Nếu bạn đang chơi xung quanh, hãy sử dụng một số cao đẹp (4 chữ số).

Cuối cùng, đối số của

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
1 cho thư viện ổ cắm rằng chúng tôi muốn nó xếp hàng lên tới 5 yêu cầu kết nối (tối đa thông thường) trước khi từ chối kết nối bên ngoài. Nếu phần còn lại của mã được viết đúng, thì đó là rất nhiều.

Bây giờ chúng tôi có một ổ cắm máy chủ trên mạng, nghe trên cổng 80, chúng tôi có thể nhập chính của máy chủ web:

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()

Trên thực tế, có 3 cách chung trong đó vòng lặp này có thể hoạt động - gửi một luồng để xử lý

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
2, tạo một quy trình mới để xử lý
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
2 hoặc tái cấu trúc ứng dụng này để sử dụng ổ cắm không chặn và ghép kênh giữa ổ cắm máy chủ của chúng tôi và bất kỳ
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
2 hoạt động nào của chúng tôi Sử dụng
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5. Thêm về điều đó sau. Điều quan trọng cần hiểu bây giờ là đây: Đây là tất cả các máy chủ của máy chủ. Nó không gửi bất kỳ dữ liệu. Nó không nhận được bất kỳ dữ liệu nào. Nó chỉ sản xuất ổ cắm của khách hàng trên mạng. Mỗi
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
2 được tạo ra để đáp ứng với một số ứng dụng khách khác của người dùng ổ cắm thực hiện
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
7 cho máy chủ và cổng mà chúng tôi ràng buộc. Ngay khi chúng tôi đã tạo ra
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
2 đó, chúng tôi quay lại lắng nghe để có nhiều kết nối hơn. Hai máy khách của người Viking có thể tự do trò chuyện - họ đang sử dụng một số cổng được phân bổ động sẽ được tái chế khi cuộc trò chuyện kết thúc.

IPC¶

Nếu bạn cần IPC nhanh giữa hai quy trình trên một máy, bạn nên xem xét các đường ống hoặc bộ nhớ được chia sẻ. Nếu bạn quyết định sử dụng ổ cắm AF_Inet, hãy liên kết ổ cắm máy chủ của máy chủ thành

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
9. Trên hầu hết các nền tảng, điều này sẽ có một lối tắt xung quanh một vài lớp mã mạng và nhanh hơn một chút.

Xem thêm

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
0 tích hợp IPC đa nền tảng vào API cấp cao hơn.

Sử dụng ổ cắm

Điều đầu tiên cần lưu ý, là ổ cắm của Trình duyệt web trên mạng và máy chủ web của máy chủ trên máy chủ của máy khách. Đó là, đây là một cuộc trò chuyện ngang hàng của người Viking. Hoặc để đặt nó một cách khác, với tư cách là nhà thiết kế, bạn sẽ phải quyết định các quy tắc nghi thức là gì cho một cuộc trò chuyện. Thông thường, ổ cắm connecting bắt đầu cuộc trò chuyện, bằng cách gửi yêu cầu hoặc có lẽ là một dấu hiệu. Nhưng đó là một quyết định thiết kế - nó không phải là một quy tắc của ổ cắm.

Bây giờ có hai bộ động từ để sử dụng để liên lạc. Bạn có thể sử dụng

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2 và
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 hoặc bạn có thể chuyển đổi ổ cắm máy khách của mình thành một con thú giống như tệp và sử dụng
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
4 và
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
5. Cái sau là cách Java trình bày ổ cắm của nó. Tôi sẽ không nói về nó ở đây, ngoại trừ để cảnh báo bạn rằng bạn cần sử dụng
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
6 trên ổ cắm. Đây là những tệp được đệm, và một sai lầm phổ biến là
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
5 một cái gì đó, và sau đó
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
4 để trả lời. Nếu không có
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
6 trong đó, bạn có thể đợi mãi mãi để trả lời, vì yêu cầu vẫn có thể nằm trong bộ đệm đầu ra của bạn.

Bây giờ chúng tôi đến khối vấp ngã chính của ổ cắm -

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2 và
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 hoạt động trên các bộ đệm mạng. Họ không nhất thiết phải xử lý tất cả các byte bạn đưa cho họ (hoặc mong đợi từ chúng), bởi vì trọng tâm chính của họ là xử lý các bộ đệm mạng. Nói chung, chúng trở lại khi các bộ đệm mạng liên quan đã được lấp đầy (
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2) hoặc làm trống (
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3). Sau đó, họ cho bạn biết họ đã xử lý bao nhiêu byte. Bạn có trách nhiệm gọi lại cho họ cho đến khi tin nhắn của bạn đã được xử lý hoàn toàn.

Khi một

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 trả về 0 byte, điều đó có nghĩa là phía bên kia đã đóng (hoặc đang trong quá trình đóng) kết nối. Bạn sẽ không nhận được thêm dữ liệu về kết nối này. Bao giờ. Bạn có thể gửi dữ liệu thành công; Tôi sẽ nói thêm về điều này sau.

Một giao thức như HTTP sử dụng ổ cắm chỉ cho một lần chuyển. Khách hàng gửi một yêu cầu, sau đó đọc trả lời. Đó là nó. Các ổ cắm bị loại bỏ. Điều này có nghĩa là một khách hàng có thể phát hiện kết thúc trả lời bằng cách nhận 0 byte.

Nhưng nếu bạn có kế hoạch sử dụng lại ổ cắm của mình để chuyển tiếp, bạn cần nhận ra rằng không có EOT trên ổ cắm. Tôi nhắc lại: Nếu một ổ cắm

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2 hoặc
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 trả về sau khi xử lý 0 byte, kết nối đã bị hỏng. Nếu kết nối chưa bị hỏng, bạn có thể chờ đợi
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 mãi mãi, bởi vì ổ cắm sẽ không nói với bạn rằng không có gì để đọc thêm (bây giờ). Bây giờ nếu bạn nghĩ về điều đó một chút, bạn sẽ nhận ra một sự thật cơ bản của ổ cắm: tin nhắn phải được cố định (yuck) hoặc được phân định (nhún vai) hoặc cho biết chúng có bao lâu (tốt hơn nhiều) hoặc Kết thúc bằng cách tắt kết nối. Sự lựa chọn hoàn toàn là của bạn, (nhưng một số cách sáng hơn những cách khác).

Giả sử bạn không muốn kết thúc kết nối, giải pháp đơn giản nhất là thông báo độ dài cố định:

class MySocket:
    """demonstration class only
      - coded for clarity, not efficiency
    """

    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(
                            socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock

    def connect(self, host, port):
        self.sock.connect((host, port))

    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent

    def myreceive(self):
        chunks = []
        bytes_recd = 0
        while bytes_recd < MSGLEN:
            chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
            if chunk == b'':
                raise RuntimeError("socket connection broken")
            chunks.append(chunk)
            bytes_recd = bytes_recd + len(chunk)
        return b''.join(chunks)

Mã gửi ở đây có thể sử dụng cho hầu hết mọi sơ đồ nhắn tin - trong Python bạn gửi chuỗi và bạn có thể sử dụng

class MySocket:
    """demonstration class only
      - coded for clarity, not efficiency
    """

    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(
                            socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock

    def connect(self, host, port):
        self.sock.connect((host, port))

    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent

    def myreceive(self):
        chunks = []
        bytes_recd = 0
        while bytes_recd < MSGLEN:
            chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
            if chunk == b'':
                raise RuntimeError("socket connection broken")
            chunks.append(chunk)
            bytes_recd = bytes_recd + len(chunk)
        return b''.join(chunks)
8 để xác định độ dài của nó (ngay cả khi nó đã nhúng các ký tự
class MySocket:
    """demonstration class only
      - coded for clarity, not efficiency
    """

    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(
                            socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock

    def connect(self, host, port):
        self.sock.connect((host, port))

    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent

    def myreceive(self):
        chunks = []
        bytes_recd = 0
        while bytes_recd < MSGLEN:
            chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
            if chunk == b'':
                raise RuntimeError("socket connection broken")
            chunks.append(chunk)
            bytes_recd = bytes_recd + len(chunk)
        return b''.join(chunks)
9). Nó chủ yếu là mã nhận được phức tạp hơn. .

Tăng cường dễ nhất là làm cho ký tự đầu tiên của tin nhắn thành một chỉ báo loại tin nhắn và có loại xác định độ dài. Bây giờ bạn có hai

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 - người đầu tiên có được (ít nhất) nhân vật đầu tiên đó để bạn có thể tìm độ dài và phần thứ hai trong một vòng lặp để có phần còn lại. Nếu bạn quyết định đi theo con đường được phân định, bạn sẽ nhận được một số kích thước chunk tùy ý, (4096 hoặc 8192 thường là phù hợp tốt cho kích thước bộ đệm mạng) và quét những gì bạn đã nhận được cho một dấu phân cách.

Một biến chứng cần biết: Nếu giao thức đàm thoại của bạn cho phép nhiều tin nhắn được gửi lại (không có một số loại trả lời) và bạn vượt qua kích thước chunk tùy ý, cuối cùng bạn có thể đọc bắt đầu một tin nhắn sau. Bạn cần phải đặt nó sang một bên và giữ nó, cho đến khi nó cần.

Tiền tố tin nhắn với độ dài của nó (giả sử, vì 5 ký tự số) trở nên phức tạp hơn, bởi vì (tin hay không), bạn có thể không nhận được tất cả 5 ký tự trong một

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3. Khi chơi xung quanh, bạn sẽ thoát khỏi nó; Nhưng trong tải mạng cao, mã của bạn sẽ rất nhanh trừ khi bạn sử dụng hai vòng
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 - phần đầu tiên để xác định độ dài, phần thứ hai để lấy phần dữ liệu của thông báo. Bẩn thỉu. Đây cũng là khi bạn phát hiện ra rằng
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2 không phải lúc nào cũng quản lý để thoát khỏi mọi thứ trong một lần. Và mặc dù đã đọc điều này, cuối cùng bạn sẽ nhận được một chút bởi nó!

Trong lợi ích của không gian, xây dựng nhân vật của bạn, (và bảo tồn vị trí cạnh tranh của tôi), những cải tiến này được để lại như một bài tập cho người đọc. Hãy chuyển sang dọn dẹp.

Dữ liệu nhị phân¶

Hoàn toàn có thể gửi dữ liệu nhị phân qua ổ cắm. Vấn đề chính là không phải tất cả các máy đều sử dụng cùng một định dạng cho dữ liệu nhị phân. Ví dụ: thứ tự byte mạng là lớn, với byte quan trọng nhất đầu tiên, do đó, một số nguyên 16 bit với giá trị

ready_to_read, ready_to_write, in_error = \
               select.select(
                  potential_readers,
                  potential_writers,
                  potential_errs,
                  timeout)
7 sẽ là hai byte hex
ready_to_read, ready_to_write, in_error = \
               select.select(
                  potential_readers,
                  potential_writers,
                  potential_errs,
                  timeout)
8. Tuy nhiên, hầu hết các bộ xử lý phổ biến (x86/AMD64, ARM, RISC-V), là ít endian, với byte ít có ý nghĩa nhất đầu tiên-tương tự
ready_to_read, ready_to_write, in_error = \
               select.select(
                  potential_readers,
                  potential_writers,
                  potential_errs,
                  timeout)
7 sẽ là connect0.

Các thư viện ổ cắm có các cuộc gọi để chuyển đổi số nguyên 16 và 32 bit - connect1 trong đó có nghĩa là mạng và có nghĩa là máy chủ có nghĩa là máy chủ, có nghĩa là ngắn và có nghĩa là dài. Trong trường hợp đặt hàng mạng là thứ tự máy chủ, những thứ này không làm gì, nhưng trong đó máy được đảo ngược byte, những thứ này trao đổi các byte xung quanh một cách thích hợp.

Trong những ngày của máy 64 bit, biểu diễn ASCII của dữ liệu nhị phân thường nhỏ hơn so với biểu diễn nhị phân. Đó là bởi vì một lượng đáng ngạc nhiên của thời gian, hầu hết các số nguyên đều có giá trị 0 hoặc có thể là 1. Chuỗi connect2 sẽ là hai byte, trong khi số nguyên 64 bit đầy đủ sẽ là 8. Tất nhiên, điều này không phù hợp với cố định với -Các thông điệp tăng cường. Quyết định, quyết định.

Ngắt kết nối

Nói đúng ra, bạn có thể sử dụng connect3 trên ổ cắm trước khi bạn connect4. connect3 là một lời khuyên cho ổ cắm ở đầu kia. Tùy thuộc vào đối số mà bạn vượt qua nó, điều đó có thể có nghĩa là tôi sẽ không gửi nữa, nhưng tôi vẫn nghe, hay tôi không nghe, câu đố tốt! Tuy nhiên, hầu hết các thư viện ổ cắm đều được sử dụng để các lập trình viên bỏ qua việc sử dụng phần nghi thức này mà thông thường là connect4 giống như connect7. Vì vậy, trong hầu hết các tình huống, một connect3 rõ ràng là không cần thiết.

Một cách để sử dụng connect3 một cách hiệu quả là trong một trao đổi giống như HTTP. Khách hàng gửi một yêu cầu và sau đó thực hiện một s0. Điều này cho máy chủ nói với máy khách này đã gửi xong, nhưng vẫn có thể nhận được. Máy chủ có thể phát hiện ra EOF EOF bằng cách nhận 0 byte. Nó có thể cho rằng nó có yêu cầu hoàn chỉnh. Máy chủ gửi trả lời. Nếu

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2 hoàn thành thành công thì thực tế, khách hàng vẫn nhận được.

Python đưa tự động tắt máy thêm một bước nữa và nói rằng khi một ổ cắm được thu thập, nó sẽ tự động thực hiện connect4 nếu nó cần. Nhưng dựa vào điều này là một thói quen rất xấu. Nếu ổ cắm của bạn biến mất mà không làm connect4, ổ cắm ở đầu kia có thể treo vô thời hạn, nghĩ rằng bạn chỉ là chậm. Vui lòng connect4 ổ cắm của bạn khi bạn hoàn thành.

Khi ổ cắm chết

Có lẽ điều tồi tệ nhất khi sử dụng ổ cắm chặn là những gì xảy ra khi phía bên kia trở nên khó khăn (mà không làm connect4). Ổ cắm của bạn có khả năng treo. TCP là một giao thức đáng tin cậy, và nó sẽ chờ đợi rất lâu trước khi từ bỏ kết nối. Nếu bạn sử dụng các chủ đề, toàn bộ chủ đề về cơ bản đã chết. Có rất nhiều bạn có thể làm về nó. Miễn là bạn không làm một cái gì đó ngu ngốc, như giữ một khóa trong khi thực hiện đọc chặn, chủ đề này thực sự tiêu tốn nhiều theo cách tài nguyên. Đừng cố giết chủ đề - một phần lý do mà các luồng hiệu quả hơn các quy trình là chúng tránh được chi phí liên quan đến việc tái chế tài nguyên tự động. Nói cách khác, nếu bạn quản lý để tiêu diệt sợi chỉ, toàn bộ quá trình của bạn có thể sẽ bị lừa.

Ổ cắm không chặn

Nếu bạn đã hiểu trước đó, bạn đã biết hầu hết những gì bạn cần biết về cơ chế sử dụng ổ cắm. Bạn vẫn sẽ sử dụng các cuộc gọi tương tự, theo cùng một cách. Nó chỉ là điều đó, nếu bạn làm đúng, ứng dụng của bạn sẽ gần như từ trong ra ngoài.

Trong Python, bạn sử dụng s6 để làm cho nó không chặn. Trong C, nó phức tạp hơn, (đối với một điều, bạn sẽ cần phải lựa chọn giữa hương vị BSD s7 và hương vị POSIX gần như không thể phân biệt s8, hoàn toàn khác với s9), nhưng nó có cùng một ý tưởng. Bạn làm điều này sau khi tạo ổ cắm, nhưng trước khi sử dụng nó. (Trên thực tế, nếu bạn là hạt dẻ, bạn có thể chuyển đổi qua lại.)

Sự khác biệt cơ học chính là

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
2,
while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3, connectsocket.gethostname()3 có thể trở lại mà không làm gì cả. Bạn có (tất nhiên) một số lựa chọn. Bạn có thể kiểm tra mã trả về và mã lỗi và thường khiến bản thân phát điên. Nếu bạn không tin tôi, một lúc nào đó hãy thử. Ứng dụng của bạn sẽ phát triển lớn, lỗi và hút CPU. Vì vậy, hãy để bỏ qua các giải pháp chết não và làm đúng.

Sử dụng

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5.

Trong C, mã hóa

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 khá phức tạp. Trong Python, nó có một miếng bánh, nhưng nó đủ gần với phiên bản C mà nếu bạn hiểu
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 trong Python, bạn sẽ gặp rất ít rắc rối với nó trong C:

ready_to_read, ready_to_write, in_error = \
               select.select(
                  potential_readers,
                  potential_writers,
                  potential_errs,
                  timeout)

Bạn vượt qua

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 ba danh sách: Đầu tiên chứa tất cả các ổ cắm mà bạn có thể muốn thử đọc; Thứ hai tất cả các ổ cắm bạn có thể muốn thử viết và lần cuối cùng (thường bị bỏ trống) những ổ cắm mà bạn muốn kiểm tra lỗi. Bạn nên lưu ý rằng một ổ cắm có thể đi vào nhiều hơn một danh sách. Cuộc gọi
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 đang chặn, nhưng bạn có thể cho nó một thời gian chờ. Đây thường là một điều hợp lý để làm - cho nó một thời gian dài tốt đẹp (nói một phút) trừ khi bạn có lý do chính đáng để làm khác.

Đổi lại, bạn sẽ nhận được ba danh sách. Chúng chứa các ổ cắm thực sự có thể đọc được, có thể ghi và có lỗi. Mỗi danh sách này là một tập hợp con (có thể trống) của danh sách tương ứng bạn đã truyền vào.

Nếu một ổ cắm nằm trong danh sách có thể đọc được đầu ra, bạn có thể gần gũi với chúng ta khi chúng ta không phải là một doanh nghiệp mà một

while True:
    # accept connections from outside
    (clientsocket, address) = serversocket.accept()
    # now do something with the clientsocket
    # in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()
3 trên ổ cắm đó sẽ trả về một cái gì đó. Ý tưởng tương tự cho danh sách có thể viết. Bạn có thể gửi một cái gì đó. Có thể không phải tất cả những gì bạn muốn, nhưng một cái gì đó tốt hơn là không có gì. .

Nếu bạn có một ổ cắm máy chủ trên máy chủ, hãy đặt nó vào danh sách tiềm năng_readers. Nếu nó xuất hiện trong danh sách có thể đọc được, công việc socket.gethostname()3 của bạn sẽ (gần như chắc chắn). Nếu bạn đã tạo một ổ cắm mới cho connect cho người khác, hãy đưa nó vào danh sách tiềm năng_writers. Nếu nó hiển thị trong danh sách có thể viết, bạn có một cơ hội tốt mà nó đã kết nối.

Trên thực tế,

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 có thể tiện dụng ngay cả khi chặn ổ cắm. Nó có một cách để xác định liệu bạn sẽ chặn - ổ cắm có thể đọc được khi có một thứ gì đó trong bộ đệm. Tuy nhiên, điều này vẫn không giúp ích gì cho vấn đề xác định liệu đầu kia được thực hiện, hoặc chỉ bận rộn với một cái gì đó khác.

Cảnh báo tính di động: Trên Unix,

# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 hoạt động cả với các ổ cắm và tệp. Don lồng thử điều này trên Windows. Trên Windows,
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 chỉ hoạt động với ổ cắm. Cũng lưu ý rằng trong C, nhiều tùy chọn ổ cắm nâng cao hơn được thực hiện khác nhau trên Windows. Trên thực tế, trên Windows, tôi thường sử dụng các chủ đề (hoạt động rất, rất tốt) với ổ cắm của tôi.
: On Unix,
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 works both with the sockets and files. Don’t try this on Windows. On Windows,
# create an INET, STREAMing socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a public host, and a well-known port
serversocket.bind((socket.gethostname(), 80))
# become a server socket
serversocket.listen(5)
5 works with sockets only. Also note that in C, many of the more advanced socket options are done differently on Windows. In fact, on Windows I usually use threads (which work very, very well) with my sockets.

Làm thế nào để các ổ cắm python kết nối với các trang web?

Python khách hàng ổ cắm đơn giản..
Tạo ổ cắm ..
Nhận địa chỉ IP máy chủ từ tên miền ..
Kết nối với máy chủ bằng địa chỉ IP ..
Gửi yêu cầu đến máy chủ ..
Nhận dữ liệu (trang web) trong mã sẽ trông giống như: # Ví dụ về máy khách trong Python.Nhập ổ cắm.nhập khẩu sys.host = 'www.pythonprograminglangle.com' port = 80 # web ..

Làm thế nào để ổ cắm hoạt động trong Python?

Ổ 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ộ, hợp lý với 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.used to send messages across a network. They provide a form of inter-process communication (IPC). The network can be a logical, local network to the computer, or one that's physically connected to an external network, with its own connections to other networks.

Ổ cắm có sử dụng TCP hoặc UDP Python không?

Đối số thứ hai xác định loại ổ cắm;Socket.sock_dgram là UDP, socket.sock_stream là một ổ cắm TCP.Tất cả điều này với điều kiện bạn đang sử dụng họ ổ cắm AF_Inet hoặc AF_Inet6.socket. SOCK_DGRAM is UDP, socket. SOCK_STREAM is a TCP socket. This all provided you are using a AF_INET or AF_INET6 socket family.