[英]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.