Hướng dẫn python socket not receiving data - ổ cắm python không nhận dữ liệu

Tôi rất mới đối với Python và có một câu hỏi cơ bản, một khách hàng có thể kết nối ổ cắm mạng có thể làm dữ liệu nhận được không? Trong câu hỏi của tôi, khách hàng là người bắt đầu kết nối, điều này có lẽ là rõ ràng nhưng tôi muốn được rõ ràng. Tôi hỏi vì tôi có một máy chủ và máy khách khác (cả Python) cho phép máy chủ nhận được một tệp từ máy khách. Nó hoạt động hoàn hảo nhưng tôi không thể nhận được một ví dụ trong đó máy khách nhận được một tệp. Python cứ nói với tôi rằng đường ống đã bị hỏng và tôi nghi ngờ nó vì ở phía khách hàng, tôi sử dụng dòng

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
6. Sự nghi ngờ của tôi là máy khách không thấy bất kỳ dữ liệu nào và do đó đóng kết nối với máy chủ. Máy chủ xem nó như một đường ống bị hỏng. Máy chủ và máy khách ở bên dưới.

server:

 #libraries to import
 import socket
 import os
 import sys
 import M2Crypto as m2c

 #information about the server the size of the message being transferred
 server_address = '10.1.1.2'
 key_port = 8888
 max_transfer_block = 1024

 FILE = open("sPub.pem","r")

 #socket for public key transfer
 keysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 keysocket.bind((server_address, key_port))
 keysocket.listen(1)

 while 1:
         conn, client_addr = keysocket.accept()
         print 'connected by', client_addr
         #sends data to the client
         data = FILE.read()
         keysocket.sendall(data)
 keysocket.close()

Client:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()

Tôi sẽ đánh giá cao bất kỳ sự giúp đỡ về vấn đề này. Cảm ơn!


Hướng dẫn về ổ cắm với Python 3 Phần 1 - Gửi và nhận dữ liệu

Chào mừng bạn đến với một hướng dẫn trên ổ cắm với Python 3. Chúng tôi có rất nhiều thứ để trang trải, vì vậy hãy nhảy ngay vào thư viện

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7 là một phần của thư viện tiêu chuẩn, vì vậy bạn đã có nó.

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Biến

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8 là ổ cắm TCP/IP của chúng tôi. AF_Inet có liên quan đến gia đình hoặc tên miền, điều đó có nghĩa là IPv4, trái ngược với IPv6 với AF_Inet6. Sock_stream có nghĩa là nó sẽ là một ổ cắm TCP, đó là loại ổ cắm của chúng tôi. TCP có nghĩa là nó sẽ được định hướng kết nối, trái ngược với kết nối không có kết nối.

Được rồi, vậy một ổ cắm là gì? Bản thân ổ cắm chỉ là một trong những điểm cuối trong giao tiếp giữa các chương trình trên một số mạng.

Một ổ cắm sẽ được gắn vào một số cổng trên một số máy chủ. Nói chung, bạn sẽ có một khách hàng hoặc loại máy chủ hoặc chương trình.

Trong trường hợp của

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
9, bạn sẽ liên kết một ổ cắm với một số cổng trên máy chủ (localhost). Trong trường hợp
s.bind((socket.gethostname(), 1234))
0, bạn sẽ kết nối một ổ cắm với máy chủ đó, trên cùng một cổng mà mã phía máy chủ đang sử dụng.

Hãy làm mã này cho đến nay phía máy chủ của chúng tôi:

s.bind((socket.gethostname(), 1234))

Đối với ổ cắm IP, địa chỉ mà chúng tôi liên kết là một bộ máy chủ và số cổng.

Bây giờ chúng tôi đã thực hiện điều đó, chúng ta hãy lắng nghe các kết nối đến. Chúng tôi chỉ có thể xử lý một kết nối tại một thời điểm nhất định, vì vậy chúng tôi muốn cho phép một số hàng đợi, chỉ cần chúng tôi có một chút nổ. Nếu ai đó cố gắng kết nối trong khi hàng đợi đầy, họ sẽ bị từ chối.

Hãy làm một hàng đợi 5:

s.listen(5)

Và bây giờ, chúng tôi chỉ lắng nghe!

while True:
    # now our endpoint knows about the OTHER endpoint.
    clientsocket, address = s.accept()
    print(f"Connection from {address} has been established.")

Mã đầy đủ cho

s.bind((socket.gethostname(), 1234))
1:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234))
s.listen(5)

while True:
    # now our endpoint knows about the OTHER endpoint.
    clientsocket, address = s.accept()
    print(f"Connection from {address} has been established.")

Bây giờ chúng ta cần phải làm mã của khách hàng!

import socket

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

Bây giờ, vì đây là khách hàng, thay vì

s.bind((socket.gethostname(), 1234))
2, chúng tôi sẽ đến
s.bind((socket.gethostname(), 1234))
3.

s.connect((socket.gethostname(), 1234))

Theo nghĩa truyền thống hơn về máy khách và máy chủ, bạn sẽ không thực sự có máy khách và máy chủ trên cùng một máy. Nếu bạn muốn có hai chương trình nói chuyện với nhau tại địa phương, bạn có thể làm điều này, nhưng thông thường, khách hàng của bạn sẽ có nhiều khả năng kết nối với một số máy chủ bên ngoài, sử dụng địa chỉ IP công cộng của nó chứ không phải

s.bind((socket.gethostname(), 1234))
4. Thay vào đó, bạn sẽ vượt qua chuỗi của IP.

Mã đầy đủ

s.bind((socket.gethostname(), 1234))
5 cho đến thời điểm này:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1234))

Được rồi, bây giờ chúng tôi chỉ chạy cả hai. Đầu tiên, hãy chạy máy chủ của chúng tôi:

s.bind((socket.gethostname(), 1234))
6

s.bind((socket.gethostname(), 1234))
7

Trên máy chủ của chúng tôi, chúng ta sẽ thấy:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
0

Tuy nhiên, khách hàng của chúng tôi chỉ thoát ra sau đó, bởi vì nó đã hoàn thành công việc của mình.

Vì vậy, chúng tôi đã thực hiện một kết nối, và điều đó thật tuyệt, nhưng chúng tôi thực sự muốn gửi tin nhắn và/hoặc dữ liệu qua lại. làm sao chúng ta làm việc đó bây giờ?

Ổ cắm của chúng tôi có thể

s.bind((socket.gethostname(), 1234))
8 và
s.bind((socket.gethostname(), 1234))
9 dữ liệu. Những phương pháp xử lý dữ liệu thỏa thuận trong bộ đệm. Bộ đệm xảy ra trong các khối dữ liệu của một số kích thước cố định. Hãy xem điều đó trong hành động:

Bên trong

s.bind((socket.gethostname(), 1234))
1, hãy thêm:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
1

Vào vòng lặp

s.listen(5)
1 của chúng tôi, vì vậy mã đầy đủ của chúng tôi cho
s.bind((socket.gethostname(), 1234))
1 trở thành:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
2

Vì vậy, chúng tôi đã gửi một số dữ liệu, bây giờ chúng tôi muốn nhận nó. Vì vậy, trong

s.bind((socket.gethostname(), 1234))
5 của chúng tôi, chúng tôi sẽ làm:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
3

Điều này có nghĩa là ổ cắm của chúng tôi sẽ cố gắng nhận dữ liệu, với kích thước bộ đệm là 1024 byte cùng một lúc.

Sau đó, chúng ta hãy làm một cái gì đó cơ bản với dữ liệu chúng ta nhận được, như in nó ra!

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
4

Tuyệt vời, mã

s.bind((socket.gethostname(), 1234))
5 đầy đủ của chúng tôi là:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
5

Bây giờ, chạy cả

s.bind((socket.gethostname(), 1234))
1 và sau đó
s.bind((socket.gethostname(), 1234))
5.
s.bind((socket.gethostname(), 1234))
1 của chúng tôi cho thấy:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
6

Trong khi

s.bind((socket.gethostname(), 1234))
5 của chúng tôi hiện cho thấy:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
7

Và nó thoát ra. Được rồi, vì vậy hãy điều chỉnh bộ đệm đó một chút, thay đổi

s.bind((socket.gethostname(), 1234))
5
s.bind((socket.gethostname(), 1234))
9 thành 8 byte cùng một lúc.

s.bind((socket.gethostname(), 1234))
5

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
8

Bây giờ, chạy lại

s.bind((socket.gethostname(), 1234))
5, và thay vào đó bạn sẽ thấy một cái gì đó như:

 # the specified libraries
 import socket
 import M2Crypto as m2c
 #file to be transferred
 FILE = open("test.txt", "r")
 #address of the server
 server_addr = '10.1.1.2'
 #port the server is listening on
 dest_port = 8888

 data = FILE.read()


 #Creates a socket for the transfer
 mysocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
 mysocket.connect( (server_addr, dest_port) )

 data = mysocket.recv(1024)
 print data
 #creates a new file to store the msg
 name = "serverPubKey.pem"

 #opens the new file and writes the msg to it
 FILE = open (name, "w")
 FILE.write(data)


 #closes the socket.
 mysocket.close()
9

Không nhìn quá nóng! Vì vậy, bạn có thể nhận ra rằng theo nghĩa đen thêm tối đa 8 ký tự, vì vậy mỗi byte là một nhân vật. Tại sao không ... Quay trở lại 1024? hoặc một số số lượng lớn. Tại sao làm việc trong bộ đệm ở tất cả?

Tại một số điểm, bất kể bạn đặt số nào, nhiều ứng dụng sử dụng ổ cắm cuối cùng sẽ mong muốn gửi một số lượng byte vượt xa kích thước bộ đệm. Thay vào đó, chúng ta có thể cần xây dựng chương trình của mình từ đầu để thực sự chấp nhận toàn bộ các tin nhắn trong các phần của bộ đệm, ngay cả khi thường chỉ có một khối. Chúng tôi làm điều này chủ yếu để quản lý bộ nhớ. Các tính toán tùy thuộc vào ứng dụng có thể thay đổi và bạn sẽ tự do chơi với kích thước bộ đệm sau này. Điều duy nhất tôi có thể chắc chắn hứa hẹn là: Bạn cần lập kế hoạch ngay từ đầu để xử lý các thông tin liên lạc trong các khối.

Đối với khách hàng của chúng tôi, làm thế nào chúng tôi có thể làm điều này? Một vòng lặp

s.listen(5)
1 có vẻ như nó có thể phù hợp với hóa đơn. Dữ liệu sẽ xuất hiện dưới dạng luồng, vì vậy thực sự, việc xử lý điều này cũng đơn giản như thay đổi tệp
s.bind((socket.gethostname(), 1234))
5 của chúng tôi thành:

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
0

Vì vậy, tại thời điểm này, chúng tôi sẽ nhận được dữ liệu này và in nó bằng các khối. Nếu chúng ta chạy

s.bind((socket.gethostname(), 1234))
5 bây giờ, chúng ta sẽ thấy:

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1

Bạn cũng nên lưu ý rằng

s.bind((socket.gethostname(), 1234))
5 của chúng tôi không còn thoát. Kết nối này bây giờ vẫn còn mở. Điều này là do vòng lặp
s.listen(5)
1 của chúng tôi. Chúng ta có thể sử dụng
while True:
    # now our endpoint knows about the OTHER endpoint.
    clientsocket, address = s.accept()
    print(f"Connection from {address} has been established.")
8 trên ổ cắm để đóng nó nếu chúng ta muốn. Chúng tôi có thể làm điều này trên máy chủ hoặc trên máy khách ... hoặc cả hai. Có lẽ bạn nên chuẩn bị cho một trong hai kết nối để giảm hoặc đóng cửa vì bất kỳ lý do gì. Ví dụ: chúng tôi có thể đóng kết nối sau khi chúng tôi gửi tin nhắn của mình trên máy chủ:

s.bind((socket.gethostname(), 1234))
1

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2

Tuy nhiên, nếu chúng ta chạy điều này, tuy nhiên, chúng ta sẽ thấy

s.bind((socket.gethostname(), 1234))
5 của chúng ta sau đó spam ra một loạt hư vô, bởi vì dữ liệu mà nó nhận được, thì không có gì. Nó trống rỗng. 0 byte, nhưng chúng tôi vẫn yêu cầu nó in ra những gì nó nhận được, ngay cả khi đó là không có gì! Chúng tôi có thể sửa chữa điều đó:

s.bind((socket.gethostname(), 1234))
5

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3

Vì vậy, bây giờ chúng tôi đang đệm qua thông điệp đầy đủ. Khi chúng ta đạt đến kết thúc, mà chúng ta lưu ý bằng cách nhận 0 byte, chúng ta phá vỡ và sau đó trả lại tin nhắn. Điều này sau đó kết thúc

s.bind((socket.gethostname(), 1234))
5. Bây giờ, khách hàng có thể cũng muốn duy trì kết nối. Làm thế nào chúng ta có thể làm điều đó? Một vòng lặp
s.listen(5)
1 khác có thể thực hiện thủ thuật.

s.bind((socket.gethostname(), 1234))
5

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4

Tất nhiên, có lẽ chúng ta sẽ một lần nữa đảm bảo

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234))
s.listen(5)

while True:
    # now our endpoint knows about the OTHER endpoint.
    clientsocket, address = s.accept()
    print(f"Connection from {address} has been established.")

5 có một thứ gì đó của chất trước khi chúng ta in nó ra:

s.bind((socket.gethostname(), 1234))
5

import socket

# create the socket
# AF_INET == ipv4
# SOCK_STREAM == TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5

Điều này hoạt động, nhưng chúng tôi có vấn đề. Điều gì xảy ra khi chúng tôi ngừng đóng ổ cắm máy khách ở phía máy chủ? Chúng tôi không bao giờ thực sự nhận được một tin nhắn! Tại sao điều này?

TCP là một giao tiếp *luồng *... vậy làm thế nào để chúng ta thực sự biết khi nào một tin nhắn thực sự xảy ra? Nói chung, chúng tôi cần cách thông báo cho ổ cắm nhận về tin nhắn và nó sẽ lớn như thế nào. Có nhiều cách mà chúng ta có thể làm điều này. Một cách phổ biến là sử dụng một loại tiêu đề luôn dẫn đến thông điệp của chúng tôi. Chúng tôi cũng có thể sử dụng một số loại chân trang, nhưng điều này có thể gây rắc rối nếu ai đó tìm hiểu về các phương pháp của chúng tôi.

Chúng tôi sẽ làm việc về điều này trong hướng dẫn tiếp theo.

Hướng dẫn tiếp theo: