2014-12-19 4 views
2

Я пытаюсь создать многопоточный udp-сервер с python.Thread UDP Socket

Вот что я делаю:

#!/usr/bin/python 
# -*- coding:Utf-8 -*- 

import sys 
import socket 
from thread import start_new_thread 


class Broker(): 
    def __init__(self, ip, port): 
     self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
     self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     self.ip = ip 
     self.port = port 
     self.s.bind((ip, port)) 
     self.listclients = [] 

def listenMod(b): 
    dic = {} 
    msg, ip = b.s.recvfrom(1024) 
    dic[msg] = ip 
    b.listclients.append(dic) 
    print msg, " is connected." 


def broker(arg): 
    try: 
     b = Broker(arg[2], int(arg[3])) 
     start_new_thread(listenMod, (b,)) 

    except Exception, e: 
     print e 
     sys.exit(-1) 


def client(arg): 
    try: 
     pass 
    except: 
     pass 

def usage(): 
    print "usage ./udps.py <-b|-c> <args>" 
    print "-b\tserver mode\n\t<args>: host port" 
    sys.exit() 

def main(): 
    i = 1 
    if len(sys.argv) > 1: 
     while i < len(sys.argv): 
      if sys.argv[1] == "-b": 
       broker(sys.argv) 
      elif sys.argv[1] == "-c": 
       pass 
      else: 
       usage() 
    else: 
     usage() 



if __name__ == '__main__': 
    main() 

всегда печатает «[Errno 48] Адрес уже используется»

Я использую это, потому что я хотел бы быть в состоянии сделать, чтобы некоторые особые вещи с моими клиентами, но также и возможность подключения новых клиентов одновременно.

+0

Вы называете 'broker()' несколько раз? Вы не можете привязать сокет к одному порту несколько раз ... Возможно, вы покажете еще один код, связанный с использованием 'broker()'. – tamasgal

+0

нет, я этого не делаю. На самом деле это работает, если я не использую: start_new_thread (listenMod, (б)) но просто: listenMod (б) – ZeenaZeek

+1

Какая строка кода потерпит неудачу? Можете ли вы предоставить полную рабочую примерную программу? –

ответ

0

Во-первых, не используйте SO_REUSEADDR. Есть legitimate uses of SO_REUSEADDR, но в самых простых случаях это не полезно, и это скрывает реальную проблему. Не стесняйтесь повторно добавлять его, если это необходимо, но только тогда, когда ваша программа работает без него.

Ваша проблема здесь в вашем main. Вы зацикливаете на количество аргументов, но никогда не увеличиваете i, поэтому он бесконечно петляет. Также вы всегда тестируете argv[1]. Если есть 4 аргумента, а второй - «-b», вы вызовете broker() 4 раза, что, очевидно, не сработает. Также обратите внимание, что если ваша петля заканчивается и основной выход, ваша программа будет немедленно завершена, поэтому вы должны хотя бы добавить while(True): sleep(5) в конце, но это не решение.

+0

Спасибо за ваш ответ. используйте SO_REUSEADDR, потому что мой код предназначен для создания прототипа UDP Hole Punching. – ZeenaZeek

+0

@ZeenaZeek Отверстие для отверстий не требует SO_REUSEADDR. Но, если вам это нужно для вашей реализации, это не проблема. SO_REUSEADDR не плох сам по себе, просто имейте в виду, что он может скрыть потенциальные проблемы. – ElderBug