鍍金池/ 問(wèn)答/Python  HTML/ python select 設(shè)置超時(shí)時(shí)間,過(guò)了一會(huì),沒(méi)有返回

python select 設(shè)置超時(shí)時(shí)間,過(guò)了一會(huì),沒(méi)有返回

我在寫(xiě)一個(gè)網(wǎng)絡(luò)服務(wù)器,centos, 跟多臺(tái)客戶(hù)端進(jìn)行交互,使用select模型,程序在跑了一段時(shí)間之后,突然在select那里卡住了,明明socket 是establish狀態(tài),上面也應(yīng)該有數(shù)據(jù)包過(guò)來(lái),但是select并沒(méi)有返回。不確定是select機(jī)制有問(wèn)題,還是其他原因,代碼:

ip="x.x.x.x"
port1 = 8322
server = socket.socket()
server.setblocking(False)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server.bind((ip,port1));
server.listen(10)
cli_socket = socket.socket()
cli_socket.setblocking(False)
host = "127.0.0.1"
port2 = 12355
cli_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
cli_socket.bind((host, port2))
cli_socket.listen(5)
inputs=[server,cli_socket,]
while True:
readable, writable, exceptional = select.select(inputs, outputs, inputs, 30)
for s in readable:
    if s is server:
        conn,address = server.accept()
        rec_buf=conn.recv(1024)
        //make some handle here, store this connection in global data
        conn.setblocking(0)
        conn.sendall("pass")
        inputs.append(conn)
    elif s is cli_socket:
        cli_conn, addr = s.accept()
        command = cli_conn.recv(1024)
        ret=command.split(',')
            if ret[0] == "OPEN":                                                
                total_key[ret[1]].conn_sock.sendall("open")
                cli_conn.send("success")
                cli_conn.close()
    else:
        rec_buf=s.recv(1024)                                        
        //make some handle here                        
        s.sendall("ok")
for s in exceptional:
    inputs.remove(s)
    s.close()
回答
編輯回答
朽鹿

有很多小問(wèn)題,比如

1        conn,address = server.accept()
2        rec_buf=conn.recv(1024)
3        //make some handle here, store this connection in global data
4        conn.setblocking(0)
5        conn.sendall("pass")

第 2 行將阻塞整個(gè)線(xiàn)程,直到對(duì)方發(fā)送數(shù)據(jù),或連接斷開(kāi)。
第 5 行因?yàn)闆](méi)有預(yù)先判斷 conn 是否可寫(xiě),操作可能失敗。

建議使用 asyncio 改寫(xiě),參考

# -*- coding: utf-8 -*-
import asyncio


async def handle_server(reader, writer):
    data = await reader.readexactly(10)
    print('recv1: {}'.format(data.decode()))
    writer.write('pass'.encode())
    writer.close()


async def handle_client(reader, writer):
    data = await reader.readexactly(4)
    if data.decode() == 'OPEN':
        writer.write('success'.encode())
    writer.close()


def new_listener(loop, ip, port, handler):
    coro = asyncio.start_server(handler, ip, port, loop=loop)
    return loop.run_until_complete(coro)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    new_listener(loop, '127.0.0.1', 8322, handle_server),
    new_listener(loop, '127.0.0.1', 12355, handle_client),
    loop.run_forever()
2017年5月26日 01:56