2015-10-13 52 views
1

重置我已經看到和閱讀了很多關於互聯網上的這一特殊問題。 我正在寫一個簡單的聊天服務器和客戶端,主要是爲了學習目的在python中使用套接字。對方將連接[錯誤104]在Python 2.7

我在這裏觀察到的一個問題。

這裏是我的服務器代碼:

__author__ = 'pchakraverti' 

import socket 
import select 
import sys 


class NickSocketMap(object): 
    count = 0 

    def __init__(self, nick, client_socket): 
     self.nick = nick 
     self.client_socket = client_socket 
     NickSocketMap.count += 1 

    @staticmethod 
    def display_count(): 
     print "Total number of clients is %d" % NickSocketMap.count 


host = "" 
port = 7575 
socket_list = [] 
nick_list = [] 
cnt = 0 
recv_buffer = 1024 


def register_nick(nick, client_socket): 
    obj = NickSocketMap(nick, client_socket) 
    nick_list.append(obj) 


def process_request(request_string, client_socket): 
    parts = request_string.split("|") 
    if parts[0] == "set_nick": 
     register_nick(parts[1], client_socket) 
     client_socket.send("nick_set") 
    elif parts[0] == "transmit_msg": 
     broadcast_message(parts[1], parts[2]) 
    return 1 


def broadcast_message(message, client_nick): 
    for s in nick_list: 
     if s.nick == client_nick: 
      try: 
       s.client_socket.send(message) 
      except socket.errno, ex: 
       print ex 
      break 


def run_server(): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    try: 
     sock.bind((host, port)) 
    except socket.errno, ex: 
     print ex 
     sys.exit(-1) 
    sock.listen(10) 
    # add the parent socket in the list 
    socket_list.append(sock) 
    # keep the server alive 
    while True: 
     try: 
      read_ready, write_ready, in_error = select.select(socket_list, [], [], 0) 
     except select.error, ex: 
      print ex 
      continue 
     for s in read_ready: 
      # check if s is the parent socket 
      if s == sock: 
       # accept new connection and append to list 
       try: 
        con, addr = s.accept() 
        if con not in socket_list: 
         socket_list.append(con) 
       except socket.errno, ex: 
        print ex 
      else: 
       try: 
        # receive packet from connected client 
        packet = s.recv(recv_buffer) 
        if not packet: 
         socket_list.remove(s) 
         read_ready.remove(s) 
         for n in nick_list: 
          if n.client_socket == s: 
           nick_list.remove(n) 
           break 
         break 
        print packet 
       except socket.errno, ex: 
        print ex 
        continue 
       process_request(packet, s) 
    sock.close() 


if __name__ == "__main__": 
    run_server() 

這裏是我的客戶端代碼:

__author__ = 'pchakraverti' 

import socket 


nick = "" 
host = "192.168.0.167" 
port = 7575 
sock = "" 


def welcome(): 
    print "Welecome to SecuChat!" 
    print "---------------------" 


def init(): 
    nick = raw_input("Enter your chat nickname : ") 
    print nick 
    global sock 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    try: 
     sock.connect((host, port)) 
    except socket.errno, ex: 
     print ex 
    sock.send("set_nick|"+nick) 
    #sock.close() 

if __name__ == "__main__": 
    welcome() 
    init() 

在客戶端的代碼,當我不做sock.close(),服務器運行成例外:

Traceback (most recent call last): 
    File "server.py", line 102, in <module> 
    run_server() 
    File "server.py", line 84, in run_server 
    packet = s.recv(recv_buffer) 
socket.error: [Errno 104] Connection reset by peer 

如何,當我添加該行時,問題不會發生。

現在我兩個問題:

我)我處理的異常在server.py,這是爲什麼不例外被處理,爲什麼它崩潰的代碼?我如何讓服務器更健壯,我缺少什麼?

II)這是什麼崩潰和異常相對於客戶端的sock.close()線背後的邏輯是什麼?

回答

11

i)您try-except塊沒有捕獲任何異常。

的第一個參數except必須要捕獲異常的類型。 socket.errno不是一個例外類,而是一個模塊。你需要捕捉socket.error

except socket.error, ex: 
    print ex 

據「崩潰」你的代碼,因爲沒有在調用堆棧的地方處理任何異常向外傳播,直到它擊中的except。如果沒有處理程序,則程序終止。

ⅱ)當客戶端終止而不關閉連接,RST分組由您的操作系統的TCP/IP堆棧發送。這大致相當於在不說再見的情況下掛斷電話。 Python通過文本「Connection reset by peer」將文本轉換爲異常。它只是意味着,既然你叫read() Python假設你期望收到一些東西,當連接突然斷開時,Python通過引發異常來告訴你這一點。

+0

明白了! Thanx隊友! – Priyabrata