簡體   English   中英

為什么這個 function 會阻塞?

[英]Why does this function block?

我有一些代碼正在從非阻塞套接字讀取數據(如果有的話)並打印它,但是當這種情況發生(接收和打印數據)時,function 然后阻塞並且不返回,除非我終止發送進程(它也使用非阻塞 stream 來發送數據)。

顯然我做錯了什么,但在我的一生中我看不到它 - 套接字是非阻塞的,我認為continue語句有些多余。 Python 不是我的主要語言,所以我假設我在這方面犯了一個愚蠢的錯誤。

這是接受連接並將它們附加到列表的套接字設置 - 我假設套接字的非阻塞性質保留在 accept() 上:

# Open socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False) # Make port non-blocking
s.bind((HOST, PORT))
s.listen(MAX_CONN)
#print("Listening on port %d" % PORT)

connection_list = []
connection_list.append(s)

while True:
    # Get the list sockets which are ready to be read through select
    readable, writable, errored = select.select(connection_list, [], [], 0) # 0 = No timeout / do not block

    for sock in readable:
        # New connection
        if sock == s:
            # New connection received through server_socket
            sockfd, addr = s.accept()
            connection_list.append(sockfd)
            print("Client (%s, %s) connected" % addr)

這是我認為有問題的接收器端 Python 代碼,它是從主循環輪詢的:

    def handle_replies():
        global connection_list
        for sock in connection_list:
            if sock != s: # Ignore our open listening socket
                try:
                    data = sock.recv(1024)
                except socket.error as e:
                    err = e.args[0]
                    if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
                        print("Would block") # Socket has no data for us
                    else:
                        # a "real" error occurred
                        print("Error: %s" % e)
                    continue # To next sock in list
                else:
                    if data:
                        print("<%s> sent %s" % (str(sock.getpeername()), data))
                    continue

如果我從另一個進程向套接字發送一些數據,我得到(例如): <('127.0.0.1', 33196)> sent b'[HELLO:STATUS]'但它會停止,直到我終止發送進程.

這是我認為正確的發送端代碼(GTK3 C 代碼)的[相關部分],在發送調用時不會阻塞或掛起:

        GSocket *sock = g_socket_connection_get_socket(connection);
        g_socket_set_blocking( sock, FALSE);

        /* use the connection */
        GInputStream * istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
        GOutputStream * ostream = g_io_stream_get_output_stream (G_IO_STREAM (connection));

        bytes = sprintf(buffer, "[HELLO:STATUS]");
        g_output_stream_write (ostream, buffer, (gsize)bytes, NULL, NULL);

那么,我在這一切中錯過了什么或做錯了什么?

好吧,@Max 的評論讓我直截了當:

    for sock in readable:
        # New connection
        if sock == s:
            # New connection received through server_socket
            sockfd, addr = s.accept()
            sockfd.setblocking(False) # This isn't inherited - set it again!
            connection_list.append(sockfd)
            print("Client (%s, %s) connected" % addr)

端口的非阻塞 state 沒有在 accept() 上繼承,添加sockfd.setblocking(False)修復了它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM