2013-06-04 94 views
1

我的python套接字服務器偵聽,然後連接到客戶端,然後客戶端將從用戶發送不確定數量的字符串。客戶端可能會關閉或失去與服務器的連接。Python套接字如何處理客戶端意外關閉

這會導致錯誤。

[Errno 10053]建立的連接被主機中的軟件中止。 或 [Errno 10054]現有連接被遠程主機強制關閉

如何處理此事件以便我可以關閉連接並重新啓動偵聽重新連接的服務器?

Python的服務器例如:

# Echo server program 
import socket 
import sys 

HOST = None    # Symbolic name meaning all available interfaces 
PORT = 7001    # Arbitrary non-privileged port 
s = None 

def startListening(): 
    print "starting to listen" 

    for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, 
            socket.SOCK_STREAM, 0, socket.AI_PASSIVE): 
     af, socktype, proto, canonname, sa = res 
     try: 
      s = socket.socket(af, socktype, proto) 
     except socket.error as msg: 
      s = None 
      continue 
     try: 
      s.bind(sa) 
      s.listen(1) 
     except socket.error as msg: 
      s.close() 
      s = None 
      continue 
     break 
    if s is None: 
     print 'could not open socket' 
     sys.exit(1) 
    conn, addr = s.accept() 
    print 'Connected by', addr 
    while 1: 
     data = conn.recv(1024) 
     if not data: 
      break 
     print data 
     message = "" 
     while not "quit" in message: 
      message = raw_input('Say Something : ') 
      conn.sendall(message) 
     #conn.send("I got that, over!") 

    conn.close() 
    print "connection closed" 

while 1: 
    startListening() 

Python客戶端例如:

# Echo client program 
import socket 
import sys 

HOST = 'localhost' # The remote host 
PORT = 7001    # The same port as used by the server 
s = None 
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM): 
    af, socktype, proto, canonname, sa = res 
    try: 
     s = socket.socket(af, socktype, proto) 
    except socket.error as msg: 
     s = None 
     continue 
    try: 
     s.connect(sa) 
    except socket.error as msg: 
     s.close() 
     s = None 
     continue 
    break 
if s is None: 
    print 'could not open socket' 
    sys.exit(1) 
s.sendall("Please send me some strings") 
data = "" 
while ("quit" not in data): 
    data = s.recv(1024) 
    print 'Received', repr(data) 
s.close() 

要重現此錯誤,運行在一個命令窗口中的服務器,並且在第二客戶端,然後關閉客戶端窗口。

回答

0

只需關閉連接並準備再次接受新連接。

處理這種情況最好的辦法是分開創建服務器套接字和接受/讀/寫循環:

create_server_socket() 
while True: 
    accept_new_connection(); 
    try: 
     read_request(); 
     write_response() 
    finally: 
     close_connection() 
+3

有處理關閉一個更優雅的方式通過使用'with'進行上下文管理。 (在'socket'模塊的文檔中沒有提到,或者在任何例子中都沒有提到它,但是檢查'socket.socket'的成員確實有'__enter __()'和'__exit __()',因此看起來是有效的上下文管理器,至少在Python 3中。) – JAB

+0

@JAB你能給出一個如何使用'with'的例子嗎? –

+0

@IlanBiala'作爲文件打開(path,'w'):#在縮進塊內對文件進行操作將在寫入模式下打開'path'指定的文件,並在'with'開始的塊被退出後自動關閉它通過成功或失敗的執行。 '__enter __()'/'__exit __()'沒有在'socket'文檔中列出,但存在於源代碼中。 – JAB

0

我認爲,當客戶端意外關閉,即根據SIGPIPE你應該處理信號

0

添加嘗試:除了:圍繞數據發送和數據的recv在服務器腳本似乎緩解這個問題:

# Echo server program 
import socket 
import sys 

HOST = None    # Symbolic name meaning all available interfaces 
PORT = 7001    # Arbitrary non-privileged port 
s = None 

def startListening(): 
    print "starting to listen" 

    for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, 
            socket.SOCK_STREAM, 0, socket.AI_PASSIVE): 
     af, socktype, proto, canonname, sa = res 
     try: 
      s = socket.socket(af, socktype, proto) 
     except socket.error as msg: 
      s = None 
      continue 
     try: 
      s.bind(sa) 
      s.listen(1) 
     except socket.error as msg: 
      s.close() 
      s = None 
      continue 
     break 
    if s is None: 
     print 'could not open socket' 
     sys.exit(1) 
    conn, addr = s.accept() 
    print 'Connected by', addr 
    while 1: 
     try: 
      data = conn.recv(1024) 
     except: 
      print "cannot recieve data" 
      break 
     if not data: 
      break 
     print data 
     message = "" 
     while not "quit" in message: 
      message = raw_input('Say Something : ') 
      try: 
       conn.sendall(message) 
      except Exception as exc: 
       #print exC# or something. 
       print "message could not be sent" 
       break 
     #conn.send("I got that, over!") 

    conn.close() 
    print "connection closed" 

while 1: 
    startListening() 
相關問題