2013-02-20 4 views
1

Итак, я делаю базовое приложение «ping», используя UDP для назначения, и все работает, кроме реализации socket.settimeout(). Я не могу понять, почему, но это связано с связанным сокетом. Это может быть просто причуда в Python, но я хотел бы подтвердить это, прежде чем документировать его. Я не ищу ответ функционального кода (это было бы обманом), но почему то, что у меня, сломано. (Например: некоторые недокументированные причина того, что Python не нравится клиент/сервер на одной машине и т.д.)python udp socket.timeout на локальной машине

Python Разъем таймаута Подробности: http://docs.python.org/2/library/socket.html#socket.socket.settimeout

В коде, представленной ниже, связи с сервером работает на той же машине успешно , но только тогда, когда клиент не привязывается к сокету. Но если он не привязан к сокету, система тайм-аута терпит неудачу (это проверяется отключением сервера, в котором все десять тайм-аутов печатаются сразу и сразу).

Примечание: код не идеален, но это класс теории сетей, а не класс программирования. Он просто должен работать в конце. Я мог бы передать его прямо сейчас и получить A, но я хочу понять, почему функция тайм-аута не работает.

EDIT: Чтобы прояснить вопрос, использование Bind в клиенте было после просмотра кода сервера была его, прежде чем я понял, 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

Зачем вам нужно связываться с локальным адресом клиента? Будет ли клиент действовать как сервер в любой момент? Если нет, нет необходимости связывать клиента вообще. Вам нужен конкретный порт только в том случае, если вам нужен ваш клиент для работы в качестве сервера, если вы не вызываете bind, он создаст случайный порт, начиная от (0 - 1023 зарезервированных) 1024 - 65535 (если я правильно помню) и это будет исходный порт в пакете UDP, исходный адрес - это адрес, в котором выполняется клиент.

Согласно Berkley Sockets

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 

Если это класс сетевой проект, и вы пытаетесь реализовать архитектуру клиент-сервер, то вы никогда не должны вызывать привязку из вашего кода клиента, потому что клиент не должен действовать так как сервер и клиент должны подключиться к серверу прослушивания, не подключенному к Клиенту.

Update:

Bind может потребоваться быть вызвана из конструкции TCP клиент-сервер, но не от модели UDP клиент-сервер, поскольку UDP является посыла и забыть дизайн и не имеет низкий уровень пакет отправить подтверждение успеха. UDP-пакет будет иметь исходный адрес и порт внутри себя.

+0

Спасибо. Я попытался связать, пытаясь исправить проблему с тайм-аутом, которая, похоже, работает, но нарушает фактическую функциональность. Причиной для его попытки было видеть, что сервер имел это, прежде чем понимать, что UDP не нуждается в этом, но это случилось, чтобы сделать тайм-аут после 1 секунды работы. – DaJJHman

0

Я нашел причину проблемы, удалив обработку исключений. При отключении сервера возникает ошибка сокета, в частности «socket.error: [Errno 10054] Существующее соединение было принудительно закрыто удаленным хостом», когда он пытается прочитать из сокета. Это, по-видимому, игнорирует функцию таймаута, когда сокет не связан в Python (поэтому таймаут работал, когда я его связал). Если я запустил сервер, но просто не отправляйте какие-либо данные (комментируя последнюю строку), программа истекает правильно, когда она не получает свой пакет обратно. Я также собираюсь использовать более специфичный обработчик исключений В конце концов, это просто причуда в Python и тот факт, что UDP не имеет отношения к подключению.

Кроме того, кто-то упомянул использование «выбрать», чтобы решить эту проблему. Я заглянул в него, и в итоге получится блок if if else, который будет работать, но предпочтительными являются нативные исключения. Спасибо всем.

-Jimmy

Смежные вопросы