문제

여기에 아주 간단한 문제가 있습니다. 많은 호스트와 동시에 통신해야하지만 각 요청이 충분하기 때문에 동기화가 필요하지 않습니다.

그로 인해 나는 스레드를 스팸 대신 비동기 소켓으로 작업하기로 결정했습니다. 이제 약간의 문제가 있습니다.

비동기 재료는 매력처럼 작동하지만 100 개의 호스트에 연결하면 100 개의 타임 아웃 (타임 아웃 = 10 초)을 받으면 1000 초를 기다렸다가 모든 연결이 실패한 것을 알기 위해 기다립니다.

비 블록 소켓 연결도 얻을 수있는 방법이 있습니까? 내 소켓은 이미 블로킹되지 않은 상태로 설정되었지만 Connect ()가 여전히 차단되고 있습니다.

시간 초과를 줄이는 것은 허용되는 솔루션이 아닙니다.

나는 파이썬에서 이것을하고 있지만,이 경우 프로그래밍 언어가 실제로 중요하지 않은 것 같습니다.

실제로 스레드를 사용해야합니까?

도움이 되었습니까?

해결책

타임 아웃을 설정할 때 소켓이 블록하므로 연결을 병렬화해야합니다. 또는 타임 아웃을 설정할 수없고 선택 모듈을 사용할 수 없습니다.

디스패처 클래스 에서이 작업을 수행 할 수 있습니다. 비동기 기준 치수. 기본을 살펴보십시오 HTTP 클라이언트 예제. 해당 클래스의 여러 인스턴스는 Connect에서 서로를 차단하지 않습니다. 스레드를 쉽게 사용하는 것처럼이 작업을 수행 할 수 있으며 소켓 타임 아웃 추적이 더 쉬워 지지만 이미 비동기 메소드를 사용하고 있기 때문에 동일한 트랙을 유지할 수 있습니다.

예를 들어, 다음은 모든 Linux 시스템에서 작동합니다.

import asyncore, socket

class client(asyncore.dispatcher):
    def __init__(self, host):
        self.host = host
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, 22))

    def handle_connect(self):
        print 'Connected to', self.host

    def handle_close(self):
        self.close()

    def handle_write(self):
        self.send('')

    def handle_read(self):
        print ' ', self.recv(1024)

clients = []
for i in range(50, 100):
    clients.append(client('cluster%d' % i))

asyncore.loop()

Cluster50 -Cluster100에서 반응이 없거나 존재하지 않는 수많은 기계가 있습니다. 이것은 즉시 인쇄를 시작합니다.

Connected to cluster50
  SSH-2.0-OpenSSH_4.3

Connected to cluster51
  SSH-2.0-OpenSSH_4.3

Connected to cluster52
  SSH-2.0-OpenSSH_4.3

Connected to cluster60
  SSH-2.0-OpenSSH_4.3

Connected to cluster61
  SSH-2.0-OpenSSH_4.3

...

그러나 이것은 차단 해야하는 getAddrinfo를 고려하지 않습니다. DNS 쿼리를 해결하는 데 문제가있는 경우 모든 것이 기다려야합니다. 아마도 DNS 쿼리를 직접 별도로 수집하고 비동기 루프에서 IP 주소를 사용해야합니다.

Asyncore보다 더 큰 툴킷을 원한다면 살펴보십시오. 꼬인 매트릭스. 들어가기에는 약간 무겁지만 Python에 대해 얻을 수있는 최고의 네트워크 프로그래밍 툴킷입니다.

다른 팁

사용 select 기준 치수. 이를 통해 여러 비 블로킹 소켓에서 I/O 완료를 기다릴 수 있습니다. 여기에 있습니다 더 많은 정보 select에서. 링크 된 페이지에서 :

C에서 코딩 select 상당히 복잡합니다. 파이썬에서는 케이크 조각이지만 C 버전에 충분히 가깝습니다. Python에서 선택을 이해하면 C에서 문제가 거의 없습니다.

ready_to_read, ready_to_write, in_error = select.select(
                  potential_readers, 
                  potential_writers, 
                  potential_errs, 
                  timeout)

당신은 통과 select 세 가지 목록 : 첫 번째에는 읽을 수있는 모든 소켓이 포함되어 있습니다. 두 번째는 당신이 쓰려고하는 모든 소켓과 오류를 확인하려는 마지막 (일반적으로 비어 있음). 소켓은 둘 이상의 목록으로 들어갈 수 있습니다. 그만큼 select 전화가 차단되지만 타임 아웃을 줄 수 있습니다. 이것은 일반적으로 합리적인 일입니다. 다른 방법으로할만한 이유가 없다면 멋진 긴 타임 아웃 (예 : 1 분)을 제공하십시오.

그 대가로 3 개의 목록을 얻을 수 있습니다. 그들은 실제로 읽을 수 있고 쓰기 가능하며 오류가있는 소켓을 가지고 있습니다. 이 목록 각각은 통과 한 해당 목록의 하위 집합 (비어 있음)입니다. 그리고 하나 이상의 입력 목록에 소켓을 넣으면 하나의 출력 목록에 최대 (최대)입니다.

소켓이 출력 읽기 가능한 목록에있는 경우,이 사업은 그와 같이 get-in-get-business로 클릭 할 수 있습니다. recv 그 소켓에서 무언가를 반환합니다. 쓰기 가능한 목록에 대해 동일한 아이디어. 당신은 할 수 있습니다 send무엇. 어쩌면 당신이 원하는 전부는 아니지만 무언가가 아무것도 아닌 것보다 낫습니다. (실제로, 합리적으로 건강한 소켓이 쓰기 가능하게 되돌아 갈 것입니다. 이는 아웃 바운드 네트워크 버퍼 공간을 사용할 수 있음을 의미합니다.)

"서버"소켓이있는 경우 Plative_Readers 목록에 넣으십시오. 읽을 수있는 목록에 나오면 수락이 (거의 확실하게) 작동합니다. 다른 사람에게 연결하기 위해 새 소켓을 만든 경우 Plative_writers 목록에 넣으십시오. 쓰기 가능한 목록에 표시되면 연결 가능성이 높습니다.

불행히도 버그를 보여주는 예제 코드가 없으므로이 블록의 출처를보기가 약간 어렵습니다.

그는 다음과 같은 일을합니다.

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
s.connect(("www.nonexistingname.org", 80))

소켓 모듈은 내부적으로 getAddrinfo를 사용합니다. 이는 특히 호스트 이름이 존재하지 않을 때 차단 작업입니다. 표준 준수 DNS 클라이언트는 이름이 실제로 존재하지 않는지 또는 느린 DNS 서버가 있는지 확인하기 위해 시간을 기다립니다.

솔루션은 IP-Addresses에만 연결하거나 비 블로킹 요청을 허용하는 DNS 클라이언트를 사용하는 것입니다. pydns.

사용 꼬인.

파이썬으로 작성된 비동기 네트워킹 엔진으로 수많은 프로토콜을 지원하며 직접 추가 할 수 있습니다. 클라이언트와 서버를 개발하는 데 사용할 수 있습니다. Connect가 차단되지 않습니다.

당신은 비동기 기준 치수? 필요한 것일 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top