2015-05-28 2 views
0

Я новичок в сетевом программировании и питоне.python multithreading server

Я пытаюсь выяснить, как выполнять разные задания на стороне сервера.

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

Мой код, как показано ниже, но он не работает:

Отредактировано: он не работает означает, что он застрянет в функции init_conn()

Как:

starting up on localhost port 8887 
Thread: 0 Connected with 127.0.0.1:48080 
# waiting 

Я изучаю структуру SocketServer, но не знаю, как это работает.

from thread import * 
import socket 

def init_conn(): 
     thread_count =0 

     # Create a TCP/IP socket 
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     # Bind the socket to the port 
     server_address = ('localhost', 8887) 

     print >>sys.stderr, 'starting up on %s port %s' % server_address 
     sock.bind(server_address) 

     # Listen for incoming connections 
     sock.listen(10) 

     #now keep talking with the client 
     while 1: 
       #wait to accept a connection - blocking call 
       conn, addr = sock.accept() 
       print 'Thread: '+ str(thread_count) + ' Connected with ' + addr[0] + ':' + str(addr[1]) 

       #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function. 
       start_new_thread(clientthread ,(conn,)) 
       thread_count +=1 
     sock.close() 

def clientthread(conn): 
     # receive data from client and send back 

def console(): 
     print 'this is console' 
     option = raw_input('-v view clients') 
     if option == 'v': 
      print 'you press v' 

def main(): 
     start_new_thread(init_conn(),()) 
     start_new_thread(console(),()) 

if __name__ == "__main__": 
    main() 
+1

Во-первых, как именно 'это не work'? Во-вторых, я не видел реализацию функции 'start_new_thread', которая может быть существенной для этой проблемы. – skyline75489

+0

'start_new_thread' - это низкоуровневая функция из пакета python' thread'. Я не могу ввести терминал после запуска server.py. – pyang

ответ

1

Возможно, проблема заключается в том, что вы запускаете программу, иногда она печатает «это консоль», а затем она заканчивается.

Первая ошибка заключается в том, что вы вызываете методы вместо передачи дескриптора в start_new_thread. Это не должно быть:

start_new_thread(init_conn,()) 

() т.е. не после имени функции.

Программа не делает многого, потому что start_new_thread() явно начинает нить, а затем ждет ее остановки. Документация довольно неясна. Лучше использовать новый модуль threading; См http://pymotw.com/2/threading/

def main(): 
    t = threading.Thread(target=init_conn) 
    t.daemon = True 
    t.start() 

    console() 

так что код будет работать до console() концов.

Предлагаю разделить сервер и инструмент командной строки. Создайте клиента, который принимает команды из командной строки и отправляет их на сервер. Таким образом, вы можете запускать консоль из любого места, и вы можете сохранить код для двух отдельных.

+0

После удаления '()' после имени функции он ничего не выводит. Кроме того, запятая между скобкой кажется причиной ошибки, которая говорит «Файл» server.py », строка 72 start_new_thread (init_conn, (,)) ^ SyntaxError: недействительный синтаксис' – pyang

+0

@pyang: Извините, я смешал это с одиночными списками аргументов. '(1)! = (1,)'. Исправлена. Я также проверяю документацию на 'start_new_thread()' и не могу ее понять. Смотрите мои правки. –

+0

У меня есть 'client.py'. Что я хочу для сервера, так это то, что я все еще могу использовать инструмент командной строки, когда у него есть поток, связанный с инициализацией соединения. 'init_conn() 'никогда не будет останавливаться, потому что он должен продолжать слушать входящие клиенты. – pyang

0

Видя, что вы новичок в Python, вы пробовали взглянуть на threading модуль, который поставляется со стандартной библиотекой?

import threading 

... #rest of your code 

while conditions==True: 
    i = threading.Thread(target=init_conn) 
    c = threading.Thread(target=console) 

    i.start() 
    c.start() 

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

0

Используя SocketServer, вы можете реализовать систему клиент/сервер. В документации приведены небольшие примеры, которые могут быть вам полезны. Вот расширенный пример оттуда:

server.py:

import SocketServer 
import os 
import logging 

FORMAT = '[%(asctime)-15s] %(message)s' 
logging.basicConfig(format=FORMAT, level=logging.DEBUG) 


class MyServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 
    # By setting this we allow the server to re-bind to the address by 
    # setting SO_REUSEADDR, meaning you don't have to wait for 
    # timeouts when you kill the server and the sockets don't get 
    # closed down correctly. 
    allow_reuse_address = True 

    request_queue_size = 10 

    def __init__(self, port): 
     self.host = os.uname()[1] 
     self.port = port 

     SocketServer.TCPServer.__init__(self, (self.host,self.port), MyTCPHandler) 

     logging.info("Server has been started on {h}:{p}".format(h=self.host,p=self.port)) 


class MyTCPHandler(SocketServer.BaseRequestHandler): 
    """ 
    The RequestHandler class for our server. 

    It is instantiated once per connection to the server, and must 
    override the handle() method to implement communication to the 
    client. 
    """ 

    def handle(self): 
     # self.request is the TCP socket connected to the client 
     # max length is here 1024 chars 
     self.data = self.request.recv(1024).strip() 

     logging.info("received: {d}".format(d=self.data)) 

     # here you may execute different functions according to the 
     # request string 

     # here: just send back the same data, but upper-cased 
     self.request.sendall(self.data.upper()) 


PORT = 8887 

if __name__ == "__main__": 
    # Create the server, binding to localhost on port 8887 
    #server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler) 
    server = MyServer(PORT) 

    # Activate the server; this will keep running until you 
    # interrupt the program with Ctrl-C 
    server.serve_forever() 

клиент.ру

import socket 
import sys 
import logging 

FORMAT = '[%(asctime)-15s] %(message)s' 
logging.basicConfig(format=FORMAT, level=logging.DEBUG) 

HOST, PORT = "workstation04", 8887 

logging.info("connect to server {h}:{p}".format(h=HOST,p=PORT)) 

# read command line 
data = " ".join(sys.argv[1:]) 

# Create a socket (SOCK_STREAM means a TCP socket) 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

try: 
    # Connect to server and send data 
    sock.connect((HOST, PORT)) 
    sock.sendall(data + "\n") 

    # Receive data from the server and shut down 
    received = sock.recv(1024) 
finally: 
    sock.close() 

logging.info("Sent:  {}".format(data)) 
logging.info("Received: {}".format(received)) 

Выходной сигнал выглядит примерно так:

стороне сервера:

> python server.py 
[2015-05-28 11:17:49,263] Server has been started on disasterarea:8887 
[2015-05-28 11:17:50,972] received: my message 

стороне клиента:

[2015-05-28 11:17:50,971] connect to server disasterarea:8887 
[2015-05-28 11:17:50,972] Sent:  my message 
[2015-05-28 11:17:50,972] Received: MY MESSAGE 

Вы можете запустить несколько клиентов (из разных консолей) параллельно , Вы можете реализовать процессор запросов на стороне сервера, который обрабатывает входящие запросы и выполняет определенные функции.

В качестве альтернативы вы можете использовать модуль python ParallelPython, который выполняет код python локально в многоядерной системе или кластере и кластерах. Проверьте примеры http.

я должен был заставить пип установить этот модуль:

pip install --allow-external pp --allow-unverified pp pp