복붙노트

[PYTHON] 파이썬에서 깨진 파이프 (SIGPIPE)를 처리하는 방법은 무엇입니까?

PYTHON

파이썬에서 깨진 파이프 (SIGPIPE)를 처리하는 방법은 무엇입니까?

필자는 각 클라이언트 연결에 대해 새로운 스레드를 생성하는 간단한 멀티 스레드 게임 서버를 파이썬으로 작성했습니다. 지금은 깨진 파이프 / SIGPIPE 오류로 인해 서버가 중단 될 때가 있습니다. 프로그램이 더 이상 존재하지 않는 클라이언트에게 응답을 보내려고 할 때 일어난다 고 나는 확신한다.

이것을 처리하는 좋은 방법은 무엇입니까? 필자가 선호하는 해결책은 전체 프로그램을 종료하는 대신 클라이언트에 대한 서버 측 연결을 닫고 계속 진행하는 것입니다.

추신 :이 질문 / 답변은 일반적인 방법으로 문제를 다룹니다. 얼마나 구체적으로 해결해야합니까?

해결법

  1. ==============================

    1.try : 문을 읽으십시오.

    try : 문을 읽으십시오.

    try:
        # do something
    except socket.error, e:
        # A socket error
    except IOError, e:
        if e.errno == errno.EPIPE:
            # EPIPE error
        else:
            # Other error
    
  2. ==============================

    2.표준 소켓 모듈을 사용한다고 가정하면 socket.error : (32, 'Broken pipe') 예외 (IOError가 아닌 다른 제안 사항)를 포착해야합니다. 이것은 원격 측의 연결이 끊어진 소켓으로 보내거나 쓰는 것과 같이 설명 된 경우에 발생합니다.

    표준 소켓 모듈을 사용한다고 가정하면 socket.error : (32, 'Broken pipe') 예외 (IOError가 아닌 다른 제안 사항)를 포착해야합니다. 이것은 원격 측의 연결이 끊어진 소켓으로 보내거나 쓰는 것과 같이 설명 된 경우에 발생합니다.

    import socket, errno, time
    
    # setup socket to listen for incoming connections
    s = socket.socket()
    s.bind(('localhost', 1234))
    s.listen(1)
    remote, address = s.accept()
    
    print "Got connection from: ", address
    
    while 1:
        try:
            remote.send("message to peer\n")
            time.sleep(1)
        except socket.error, e:
            if isinstance(e.args, tuple):
                print "errno is %d" % e[0]
                if e[0] == errno.EPIPE:
                   # remote peer disconnected
                   print "Detected remote disconnect"
                else:
                   # determine and handle different error
                   pass
            else:
                print "socket error ", e
            remote.close()
            break
        except IOError, e:
            # Hmmm, Can IOError actually be raised by the socket module?
            print "Got IOError: ", e
            break
    

    이 예외는 닫혀진 소켓에 대한 첫 번째 쓰기에서 항상 발생하는 것은 아니며, 일반적으로 두 번째 쓰기 (첫 번째 쓰기에서 작성된 바이트 수가 소켓의 버퍼 크기보다 큰 경우는 제외)입니다. 응용 프로그램이 원격 종료가 이미 연결이 끊어져있을 때 첫 번째 쓰기에서 데이터를 수신했다고 생각할 경우이를 염두에 두어야합니다.

    select.select () (또는 poll)를 사용하여이 문제의 발생률을 줄일 수는 있지만 완전히 제거 할 수는 없습니다. 쓰기를 시도하기 전에 피어에서 읽을 준비가 된 데이터를 확인하십시오. select가 피어 소켓에서 읽을 수있는 데이터가 있다고보고하면 socket.recv ()를 사용하여 읽습니다. 이 메소드가 하늘의 캐릭터 라인을 돌려주는 경우, 원격 피어는 접속을 닫습니다. 아직 여기에는 경쟁 조건이 있으므로 예외를 잡아서 처리해야합니다.

    Twisted는 이런 종류의 일에 아주 좋습니다. 그러나 이미 꽤 많은 코드를 작성한 것 같습니다.

  3. ==============================

    3.SIGPIPE (비록 내가 EPIPE를 의미 할까?)는 소켓을 셧다운하고 데이터를 보낼 때 소켓에서 발생한다. 간단한 해결책은 데이터를 보내기 전에 소켓을 종료하지 않는 것입니다. 이것은 파이프에서도 발생할 수 있지만, 네트워크 서버이므로 사용자가 경험 한 것처럼 들리지는 않습니다.

    SIGPIPE (비록 내가 EPIPE를 의미 할까?)는 소켓을 셧다운하고 데이터를 보낼 때 소켓에서 발생한다. 간단한 해결책은 데이터를 보내기 전에 소켓을 종료하지 않는 것입니다. 이것은 파이프에서도 발생할 수 있지만, 네트워크 서버이므로 사용자가 경험 한 것처럼 들리지는 않습니다.

    또한 각 스레드의 일부 최상위 핸들러에서 예외를 잡아 내기위한 반창고를 적용 할 수도 있습니다.

    물론 각 클라이언트 연결마다 새 스레드를 생성하는 대신 Twisted를 사용한 경우이 문제가 발생하지 않을 것입니다. 여러 스레드가 동일한 I / O 채널을 처리하는 경우 닫기 및 쓰기 작업의 순서를 올바로 지정하는 것이 매우 어렵습니다 (응용 프로그램에 따라 불가능할 수도 있음).

  4. ==============================

    4.나는 똑같은 질문에 직면 해있다. 하지만 다음에 동일한 코드를 제출하면 작동합니다. 처음으로 그것이 고장 났을 때 :

    나는 똑같은 질문에 직면 해있다. 하지만 다음에 동일한 코드를 제출하면 작동합니다. 처음으로 그것이 고장 났을 때 :

    $ packet_write_wait: Connection to 10.. port 22: Broken pipe
    

    두 번째로 작동합니다.

    [1]   Done                    nohup python -u add_asc_dec.py > add2.log 2>&1
    

    이유는 현재 서버 환경에 관한 것일 수 있습니다.

  5. ==============================

    5.내 대답은 S.Lott 's에 매우 가깝다.

    내 대답은 S.Lott 's에 매우 가깝다.

    try:
        # do something
    except IOError, e:
        # ooops, check the attributes of e to see precisely what happened.
        if e.errno != 23:
            # I don't know how to handle this
            raise
    

    여기서 "23"은 EPIPE에서 얻은 오류 번호입니다. 이렇게하면 사용 권한 오류 또는 사용자가 갖추고 있지 않은 다른 것을 처리하지 않습니다.

  6. from https://stackoverflow.com/questions/180095/how-to-handle-a-broken-pipe-sigpipe-in-python by cc-by-sa and MIT license