2016-11-08 214 views
1

我正在寫一個簡單的聊天,目前它只是連接一個用戶。Python:線程只能啓動一次

bootchat/ 
    --server.py 
    --client.py 
    --libbootchat/ 
    --bootchat_connection.py 
    --bootchat_server.py 
    --bootchat_user.py 

代碼:

client.py

# imports 
import libbootchat.bootchat_user as user 
import socket 

print("Welcome on BootChat") 


nickname = input("nickname : ") 

bootchat_user = user.BootchatUser(nickname) 

server.py

# imports 
import socket 
import signal 
import libbootchat.bootchat_server as server 
import libbootchat.bootchat_connection as connection 

print("Starting server...") 
bootchat_server = server.BootchatServer() 



while True: 
    bootchat_server.accept_connection() 
    bootchat_server.start() 

bootchat_connection.py

class BootchatConnection(): 

    def __init__(self, socket, informations=None): 
     self.socket = socket 

     if informations: 
      self.ip = informations[0] 
      self.port = informations[1] 

    def connect_to_server(self, ip, port): 
     self.socket.connect((ip, port)) 

    def send_to_server(self, msg): 
     self.socket.send(msg.encode()) 

    def recv_from_client(self): 
     return self.socket.recv(1024).decode() 

bootchat_user.py

from libbootchat.bootchat_connection import BootchatConnection 
import socket 

class BootchatUser: 
    nb_users = 0 

    def __init__(self, nickname): 
     self.nickname = nickname 
     connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.bootchat_connection = BootchatConnection(connection) 
     self.bootchat_connection.connect_to_server("localhost", 15297) 
     self.send_message(nickname) 

    def send_message(self, msg): 
     self.bootchat_connection.send_to_server(msg) 

bootchat_server.py

import socket 
from threading import Thread 
from libbootchat.bootchat_connection import BootchatConnection 

class BootchatServer(Thread): 

    def __init__(self): 
     Thread.__init__(self) 
     self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.listener.bind(('', 15297)) 
     self.listener.listen(5) 

    def accept_connection(self): 
     socket, infos = self.listener.accept() 
     self.bootchat_connection = BootchatConnection(socket, infos) 

    def run(self): 
     print("[INFO] New user connected from {}".format(self.bootchat_connection.ip)) 
     nickname = self.bootchat_connection.recv_from_client() 
     print("[INFO] User from {} now logged at {}".format(self.bootchat_connection.ip, nickname)) 

問題:

我啓動服務器,我開始第一個客戶,我送一個暱稱和我哈沒有問題,我的服務器打印正確「新用戶連接...」,但之後,我開始第二個客戶端,我有一個錯誤。這是我的server.py的輸出:

Starting server... 
[INFO] New user connected from 127.0.0.1 
[INFO] User from 127.0.0.1 now logged at Alex 
Traceback (most recent call last): 
    File "server.py", line 14, in <module> 
    bootchat_server.start() 
    File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/threading.py", line 840, in start 
    raise RuntimeError("threads can only be started once") 
RuntimeError: threads can only be started once 

任何想法?謝謝

+0

不要使每個文件一類,你可以把一切都在一個文件中。 – Daniel

+1

正如錯誤消息所示:第一個客戶端連接後,您已經有一個'bootchat_server'線程在運行。你不能用同一個線程對象啓動另一個線程。您可能想要在accept後傳遞套接字來創建處理程序線程。 – dhke

+0

有效地我只有一個對象** ** bootchat_server這樣我就可以啓動多個** **開始 – Alexandre

回答

2

生成每個連接一個新的線程:

class BootchatServer(object): 

    def __init__(self): 
     self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.listener.bind(('', 15297)) 
     self.listener.listen(5) 

    def accept_connection(self): 
     socket, infos = self.listener.accept() 
     connection = BootchatConnection(socket, infos) 
     thread = Thread(target=self.process_connection, args=(connection,)) 
     thread.start() 

    def process_connection(self, connection): 
     print("[INFO] New user connected from {}".format(connection.ip)) 
     nickname = connection.recv_from_client() 
     print("[INFO] User from {} now logged at {}".format(connection.ip, nickname)) 

print("Starting server...") 
bootchat_server = server.BootchatServer() 

while True: 
    bootchat_server.accept_connection() 
+0

完美地工作,謝謝 – Alexandre

+0

只需要在哪裏添加thread.join()? – Alexandre