连接由 Python 2.7 中的 peer [errno 104] 重置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33111556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:48:18  来源:igfitidea点击:

Connection reset by peer [errno 104] in Python 2.7

pythonpython-2.7sockets

提问by Priyabrata

I've seen and read a lot about this particular issue on the internet. I am writing a simple chat server and client using socket in python for learning purpose mainly.

我已经在互联网上看到并阅读了很多关于这个特定问题的信息。我正在使用python中的套接字编写一个简单的聊天服务器和客户端,主要用于学习目的。

I've observed an issue here.

我在这里观察到一个问题。

Here is my server code :

这是我的服务器代码:

__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()

and here is my client code:

这是我的客户端代码:

__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()

In the client code, when I don't do the sock.close(), the server runs into an exception :

在客户端代码中,当我不这样做时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

how ever, when I add that line, the problem doesn't occur.

但是,当我添加该行时,问题不会发生。

Now I've two questions :

现在我有两个问题:

i) I've handled exceptions in the server.py, why is this exception not being handled and why is it crashing the code ? How can I make the server more robust and what am I missing ?

i) 我已经处理了 server.py 中的异常,为什么这个异常没有被处理,为什么它会导致代码崩溃?我怎样才能使服务器更健壮,我错过了什么?

ii) What is the logic behind this crash and exception in relation to the sock.close()line in the client ?

ii)sock.close()与客户端中的行相关的崩溃和异常背后的逻辑是什么?

采纳答案by cg909

i) Your try-except block doesn't catch any exceptions.

i) 您的 try-except 块不会捕获任何异常。

The first argument to exceptmust be the type of the exception you want to catch. socket.errnois not an exception class but a module. You need to catch socket.error:

的第一个参数except必须是您要捕获的异常的类型。socket.errno不是异常类而是模块。你需要抓住socket.error

 except socket.error, ex:
     print ex

It "crashes" your code because any exception that isn't handled somewhere in the call stack propagates outwards until it hits an except. If there is no handler the program is terminated.

它使您的代码“崩溃”,因为调用堆栈中某处未处理的任何异常都会向外传播,直到遇到except. 如果没有处理程序,程序将终止。

ii) When the client terminates without closing the connection, a RSTpacket is sent by the TCP/IP stack of your OS. This is roughly the equivalent of hanging up a phone without saying goodbye. Python converts this into an exception with the text "Connection reset by peer". It simply means that since you called read()Python assumed you expect to receive something and when the connection suddenly disconnected, Python informs you of this by raising the exception.

ii) 当客户端在没有关闭连接的情况下终止时RST,您的操作系统的 TCP/IP 堆栈会发送一个数据包。这大致相当于挂断电话而不说再见。Python 将其转换为带有文本“Connection reset by peer”的异常。这只是意味着,由于您调用read()Python 时假设您希望收到某些东西,而当连接突然断开时,Python 会通过引发异常来通知您这一点。