Hướng dẫn python flush input buffer - bộ đệm đầu vào python flush

Tôi đang cố gắng đảm bảo rằng mỗi lần tôi gọi hàm ổ cắm. Bộ đệm của tôi được gửi (xóa) đến máy chủ của tôi (trong C bằng cách sử dụng ổ cắm UNIX).

Từ sự hiểu biết của tôi (và từ những gì tôi thấy trên bảng này) chỉ vô hiệu hóa Algo cằn nhằn. nên làm điều đó nhưng máy chủ của tôi vẫn nhận được dữ liệu của tôi trong đoạn 4096 byte (bộ mặc định) ...

Tôi đang sử dụng mã sau trong Python v2.5.4:

 self.sck = socket( AF_INET, SOCK_STREAM )

 self.sck.setsockopt( IPPROTO_TCP, TCP_NODELAY, 1 ) # That doesn't seems to work...

 self.sck.connect( ( "127.0.0.1", "12345" ) )

 while( 1 ):
      self.sck.send( "test\n" )
      self.sck.send( "" ) # Still trying to flush...

Kích hoạt/vô hiệu hóa TCP_Nodelay dường như không có tác dụng gì ... Đây có phải là một lỗi hay tôi đang thiếu một cái gì đó?

Tia

Hỏi ngày 10 tháng 12 năm 2010 lúc 10:24Dec 10, 2010 at 10:24Dec 10, 2010 at 10:24

TCP không cung cấp bất kỳ loại "gói" được đảm bảo nào gửi đến đầu kia. Bạn đang gửi dữ liệu nhanh nhất có thể và TCP rất hữu ích để tăng dữ liệu thành nhiều nhất có thể gửi cùng một lúc. Máy chủ của bạn đang nhận dữ liệu 4096 byte tại một thời điểm, có lẽ vì đó là những gì nó yêu cầu (trong cuộc gọi recv()).

TCP là một giao thức luồng và do đó bạn sẽ phải thực hiện một số loại tự đóng khung. Không có ranh giới thông điệp tích hợp.

Đã trả lời ngày 10 tháng 12 năm 2010 lúc 10:45Dec 10, 2010 at 10:45Dec 10, 2010 at 10:45

Greg Hewgillgreg HewgillGreg HewgillGreg Hewgill

910K178 Huy hiệu vàng1131 Huy hiệu bạc1267 Huy hiệu đồng178 gold badges1131 silver badges1267 bronze badges178 gold badges1131 silver badges1267 bronze badges

1

Cách duy nhất tôi có một công việc để làm việc (trở lại với máy khách C) là sử dụng:

my_writer_obj = mysock.makefile(mode='w', ...)
my_writer_obj.write('my stuff')
my_writer_obj.flush()

Ưu điểm lớn là my_writer_obj mặc định vào chế độ văn bản, do đó không còn dịch byte nữa.

Tạo một đối tượng đầu đọc không diễn ra suôn sẻ, nhưng tôi không cần phải tuôn ra ở bên đó.

Đã trả lời ngày 18 tháng 7 năm 2014 lúc 22:52Jul 18, 2014 at 22:52Jul 18, 2014 at 22:52

3

Không có cách nào để đảm bảo kích thước của các khối dữ liệu được gửi. Nếu bạn muốn đảm bảo rằng tất cả dữ liệu bạn muốn gửi là gửi, bạn có thể đóng kết nối:

self.sck.close()

Cũng lưu ý rằng n = socket.send () trả về số lượng byte được gửi thực tế. Nếu bạn chắc chắn muốn gửi tất cả dữ liệu, bạn nên sử dụng

self.sck.sendall()

hoặc lặp qua dữ liệu gửi:

while data:
    n = self.sck.send(data)    
    data = data[n:]

(Nhưng điều đó gần giống như Sendall ()). Nếu bạn muốn nhận dữ liệu trong các khối lớn hơn, bạn có thể tăng kích thước của bộ đệm trong recv (), nhưng điều này chỉ làm cho kích thước chunk có thể lớn hơn. Không có gì đảm bảo rằng dữ liệu đến trong các kích thước này.

Đã trả lời ngày 10 tháng 12 năm 2010 lúc 11:20Dec 10, 2010 at 11:20Dec 10, 2010 at 11:20

XUBUNTIXXUBUNTIXxubuntixxubuntix

2.32518 Huy hiệu bạc19 Huy hiệu đồng18 silver badges19 bronze badges18 silver badges19 bronze badges

2

Đây là một câu hỏi phổ biến về giao thức TCP. Bản thân TCP không có cách nào để gửi dữ liệu trong các khối cụ thể. Nó chỉ được thiết kế để gửi luồng dữ liệu. Nếu bạn cần chức năng như vậy, bạn nên tự thực hiện nó. Ví dụ: gửi các khối của bạn trong các dòng riêng biệt hoặc trước tiên gửi kích thước chunk và sau đó là chính đoạn.

Trong hầu hết các trường hợp, bạn không cần quan tâm đến thuật toán chà xát. Thuật toán này được mô tả tốt hơn bằng tên tcp_nodelay. Nếu bạn vô hiệu hóa nó, bạn có thể đạt được sự chậm trễ nhỏ hơn cho các khối nhỏ nhưng tốc độ thấp hơn cho các khối lớn cùng một lúc.

Đã trả lời ngày 9 tháng 3 năm 2018 lúc 13:33Mar 9, 2018 at 13:33Mar 9, 2018 at 13:33

Alyaxeyalyaxeyalyaxeyalyaxey

1.10912 Huy hiệu bạc10 Huy hiệu đồng12 silver badges10 bronze badges12 silver badges10 bronze badges

Trong Linux, điều này là có thể với một cuộc gọi đến ioctl:

SIOCOUTQ trả về số lượng dữ liệu unsent trong ổ cắm gửi hàng đợi. Ổ cắm> không được ở trạng thái lắng nghe, nếu không một lỗi (EINVAL) được trả về. SIOCOUTQ được định nghĩa trong. Ngoài ra, bạn có thể sử dụng> tiocoutq đồng nghĩa, được xác định trong. Returns the amount of unsent data in the socket send queue. The > socket must not be in LISTEN state, otherwise an error (EINVAL) is returned. SIOCOUTQ is defined in . Alternatively, you can use > the synonymous TIOCOUTQ, defined in .
Returns the amount of unsent data in the socket send queue. The > socket must not be in LISTEN state, otherwise an error (EINVAL) is returned. SIOCOUTQ is defined in . Alternatively, you can use > the synonymous TIOCOUTQ, defined in .

Nhìn nhanh đến linux/sockios.h:

/* Linux-specific socket ioctls */
#define SIOCINQ         FIONREAD
#define SIOCOUTQ        TIOCOUTQ        /* output queue size (not sent + not acked) */

Vì vậy, áp dụng điều này là khá dễ dàng:

import socket

def flush_socket(sock: socket.socket) -> bool:
    from ctypes import c_ulong
    from time import sleep
    from termios import TIOCOUTQ
    from fcntl import ioctl

    while sock.fileno() != -1: # if fd is -1, then it has been probably close()'d
        remaining = c_ulong.from_buffer_copy(
            ioctl(sock.fileno(), TIOCOUTQ, bytearray(8), False)).value

        if remaining == 0:
            # all data has been sent and ACKed
            return True

        # wait a bit before retrying,
        # sleep(0) was meant like yield current thread,
        # but will probably be close to busy-waiting,
        # feel free to change it to fit your needs
        sleep(0)

    # not all data has been sent
    return False

Đã trả lời ngày 30 tháng 4 năm 2021 lúc 11:37Apr 30, 2021 at 11:37Apr 30, 2021 at 11:37

ZaffyzaffyZaffyZaffy

Huy hiệu vàng 16K849 Huy hiệu bạc76 Huy hiệu đồng8 gold badges49 silver badges76 bronze badges8 gold badges49 silver badges76 bronze badges