2013-02-20 5 views
1

그래서 할당을 위해 UDP를 사용하는 기본적인 "핑"응용 프로그램을 만들고 있고 socket.settimeout() 구현을 제외한 모든 기능이 작동합니다. 왜 그런지 알 수는 없지만 바인딩 된 소켓과 관련이 있습니다. 그것은 단지 파이썬의 변종 일지 모르지만 필자가 문서화하기 전에 그것을 확인하고 싶습니다. 나는 기능적인 코드 응답 (부정 행위)을 찾고있는 것이 아니라 오히려 내가 가지고있는 것이 왜 고장 났는가를 찾고있다. (예 : 파이썬 등 동일한 시스템에서 클라이언트/서버 좋아하지 않는 것을 문서화되지 않은 이유)로컬 시스템의 파이썬 udp socket.timeout

파이썬 소켓 시간 초과 세부 사항 : 아래에 표시되는 코드에서 http://docs.python.org/2/library/socket.html#socket.socket.settimeout

, 서버가 동일한 시스템에서 실행와의 통신이 성공 클라이언트가 소켓에 바인드하지 않는 경우에만 가능합니다. 그러나 소켓에 바인딩하지 않으면 시간 초과 시스템이 실패합니다 (이 시간은 10 개의 시간 제한이 모두 즉시 및 즉시 인쇄되는 서버를 끄면 테스트됩니다).

참고 : 코드는 이상적이지는 않지만 네트워킹 이론 클래스이며 프로그래밍 클래스는 아닙니다. 그것은 결국 작동해야합니다. 나는 지금 당장 그것을 건네 줄 수 있고 A를 얻을 수 있지만 시간 초과 기능이 작동하지 않는 이유를 알고 싶습니다.

편집 :이 문제를 명확히하기 위해 클라이언트에서 바인드의 사용, 나는 UDP는 필요하지 않습니다 실현,하지만 제대로 타임 아웃 기능을 작동하게하는 일이 전에 서버의 코드가 있었다보고 난 후에했지만, 정상 작동을 중단시킵니다. socket.settimeout() 선언은 TCP에서만 작동 할 수 있습니까?

클라이언트 코드 (시간 제한이있는) :

import socket 
import time 
import select 


data = "Re-verify our range to target... one ping only. \n" 

addrDest = ("127.0.0.1",8675) 
addrLocal = ("127.0.0.1",12345) 

totalTime = 0 
averageTime = 0 
totalPings = 0 
#timeout_seconds = 1.0 

UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 
UDPSock.bind(addrLocal) 
# adding bind here even though it's UDP makes timeout work, 
# but breaks normal functionality 
UDPSock.settimeout(1) 


while (totalPings < 10): 
totalPings = (totalPings + 1) 
start = time.clock() 
str_list = [] 
str_list.append(str(totalPings)) 
str_list.append(" ") 
str_list.append(str(start)) 
str_list.append(" ") 
str_list.append(data) 
dataOut = ''.join(str_list) 
UDPSock.sendto(dataOut,addrDest) 
try: 
     dataIn,addrIn = UDPSock.recvfrom(1024) 
     print dataIn.strip(),"\n",addrIn 
     elapsed = ((time.clock() - start) * 1000) 
     print elapsed, " ms round trip" 
except socket.error: 
     print "Connection timed out for Packet #", totalPings 

서버 코드 :

import socket 

UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 

# (to all IP addresses on this system) 
listen_addr = ("",8675) 
UDPSock.bind(listen_addr) 

# Report on all data packets received and 
# where they came from in each case (as this is 
# UDP, each may be from a different source and it's 
# up to the server to sort this out!) 
while True: 
    data,addr = UDPSock.recvfrom(1024) 
    print data.strip(),addr 
    UDPSock.sendto(data,addr) 
+0

당신이 읽기 타임 아웃을 사용하려면

:'수입 select'과'select.select ([UDPSock], [], [], 시간 제한)를 사용는' – User

+0

나는 선택 방법을 시도했다. 복잡 한 일들, 그리고 목록으로 반환 된 모든 것을 다룰 필요가 없어서 정말 잘 작동하지 않았다. 결국 서버가 꺼지면 연결이 강제로 닫히는 예외로 판명되었고, 내 일반 소켓 예외 잡힌 핸들 – DaJJHman

답변

2

왜 클라이언트의 로컬 주소에 바인드해야합니까? 클라이언트가 언제든지 서버 역할을합니까? 그렇지 않으면 클라이언트를 전혀 바인드 할 필요가 없습니다. 클라이언트가 서버로 작동해야하는 경우에만 특정 포트가 필요합니다. 바인드를 호출하지 않으면 임의의 포트 번호 (0 - 1023이 예약 됨) 1024 - 65535 (올바르게 기억 된 경우)와 UDP 패킷의 소스 포트, 소스 주소는 클라이언트가 실행되는 주소입니다. 이것은 네트워킹 클래스 프로젝트이며 클라이언트 역할을해서는 안하기 때문에 당신이 당신의 클라이언트 코드 내에서 바인드을에서 호출해서는 안 클라이언트 - 서버 아키텍처를 구현하려는 경우 버클리 소켓

bind() assigns a socket to an address. When a socket is created using socket(), 
it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts 

에 따르면

서버 및 클라이언트는 클라이언트에 연결하는 서버가 아닌 수신 서버에 연결해야합니다.

업데이트 : 바인딩은 UDP는 전송이기 때문에 TCP 클라이언트 - 서버 디자인에서 아니지만 UDP 클라이언트 - 서버 모델에서 호출과 디자인을 잊을 수해야 할 수 있습니다 및 낮은 수준이없는

패킷은 성공 승인을 보낸다. UDP 패킷은 Source Address와 Port 자체를 가지고 있습니다.

+0

감사. 시간 제한 문제를 해결하려고 시도하는 동안 바인드를 시도했는데 작동하는 것으로 보이지만 실제 기능은 손상됩니다. 서버가 UDP를 필요로하지 않는다는 것을 깨닫기 전에 서버가 그것을 보았지만 1 초가 지나면 타임 아웃이 발생했기 때문입니다. – DaJJHman

0

예외 처리를 제거하여 문제의 원인을 발견했습니다. 소켓에서 읽기를 시도 할 때 서버가 꺼져있을 때 소켓 오류가 발생합니다. 구체적으로 "socket.error : [Errno 10054] 기존 연결이 원격 호스트에 의해 강제로 닫혔습니다." 이것은 소켓이 파이썬에서 바인드되어 있지 않을 때 타임 아웃 기능을 명백히 무시합니다 (타임 아웃이 바인딩 된 이유입니다). 서버를 실행하지만 마지막 줄에 주석을 달아 데이터를 보내지 않으면 프로그램이 패킷을받지 못하면 올바르게 시간 초과됩니다. 좀 더 구체적인 예외 핸들러를 사용하려고합니다. 결국에는 파이썬의 단점이자 UDP가 연결없는 것입니다.

또한 누군가이 문제를 해결하기 위해 "선택"을 사용한다고 말했습니다. 나는 그것을 들여다 보았고, if ... else 구문 블록으로 끝날 것이지만 네이티브 예외가 선호된다. 감사합니다. ... 지미