2017-04-12 92 views
0

对于套接字编程和线程的总体来说,这是一个新兴的问题,我的问题可能是由于误解了它们的工作原理。我正在尝试使用线程来创建充当客户端和服务器的东西。永远在后台运行python线程化的TCP服务器

以下: https://docs.python.org/3/library/socketserver.html#asynchronous-mixins

我创建了一个客户端类去与服务器无论从主类执行。服务器通常理应启动并没有给出任何错误,但是当我尝试从客户端连接,它在以下失败:

# In client connection 
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
    sock.connect((ip, port)) 

我得到的错误是:

Traceback (most recent call last): 
    File "./<project>", line 61, in <module> 
    client.start_client(serverInfo) 
    File "/home/<username>/Documents/Github/project/client.py", line 54, in <startclient> 
    <connectionMethod>(cmd) 
    File "/home/<username>/Documents/Github/project/client.py", line 112, in <connectionMethod> 
    sock.connect((remoteHOST,remotePORT)) 
    ConnectionRefusedError: [Errno 111] Connection refused 

即使当我修改服务器从代码中所引用的蟒蛇页面(只是为了一个特定的端口,1234上运行),并尝试以

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 
    sock.connect(('127.0.0.1',1234)) 
    sock.sendall('Test message') 

我得到了同样的问题连接到该端口

Traceback (most recent call last): 
    File "<stdin>", line 2, in <module> 
ConnectionRefusedError: [Errno 111] Connection refused 

为什么服务器拒绝连接?没有防火墙规则或iptables的地方,运行的例子有客户端和套接字一起从网站工作,但即使删除server.shutdown()线,它仍然立即自杀。

我错过了什么吗?

我期待的行为是:

./programA 
<server starts on port 30000> 

./programB 
<server starts on port 30001> 
<client starts> 

---输入/输出---

从客户答:

/connect 127.0.0.1 30001 
CONNECTED TO 127.0.0.1 30001 

ON客户B:

CONNECTION FROM 127.0.0.1 30000 

基本上一旦客户端连接在第一时间,他们可以通过键入到提示,这只是创建另一个插座靶向“远程” IP和端口发送关闭消息(即时通讯)彼此通信。因为他们实际上不负责接收任何事情,所以套接字是剩余的关闭。

我会很感激任何帮助,我可以得到这一点。

+0

你既可以使每个客户端也是一个服务器,或者让主服务器手柄通过指定客户端标识符 –

+0

@ t.m.adam所有连接自己讲法不当,但每个客户_was_也是一个服务器。本质上,客户端提示符是一个类,线程服务器是一个类。这个问题来自python文档中给出的threadedPSPServer socketserver示例。实际上,这听起来可能并不适用于超时。我设法通过使用标准套接字和绑定来解决我的问题。我不确定是否在socketserver中没有使用“ThreadingMixIn”或它们的特定版本有任何问题,但到目前为止我还没遇到任何问题。我现在将标记我的解决方案,因为它似乎工作。 – user2763113

回答

0

顺便说一句,我已经取得了突破性的东西。虽然我不能完全肯定为什么它这样做,threadedTCPServer(因为它是Python文档)是基本上不能用于此目的,实际上在一个线程不会采取行动的权利,同时。相反,我选择了手工创建一个套接字服务器,像这样:

import threading 
import socket 

def simpleServer(): 
    HOST = '127.0.0.1' 
    PORT = 3000 
    sock = socket.socket() 
    sock.bind((HOST,PORT)) 

    s.listen(5) 
    while True: 
     conn, addr = s.accept() 
     msg = str(conn.recv(1024),'utf8') 
     c.send(bytes('GOT: {0}'.format(msg),'utf8') 
     c.close() 

if __name__ == '__main__': 

    server_thread = threading.Thread(target=simpleServer) 
    server_thread.start() 

    # Make connections based on '<ip>:<port>:<msg>' 
    while True: 
     cmd = input('>> ') 

     try: 
      parts = cmd.split(':') 
      ip = parts[0] 
      port = parts[1] 
      msg = parts[2] 

      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 
       sock.connect((ip,port)) 
       sock.sendall(bytes(msg,'utf8')) 
       print(str(sock.recv(1024),'utf8')) 

     except Exception as e: 
      print(e) 

的代码是非常基本的(也可能不是最好的),但我刚刚测试,它绝对是现在的工作。我根据我看到的解决方案改编了这段代码:Why am I getting the error "connection refused" in Python? (Sockets)

我必须重新调整大部分代码,但我认为它应该可以正常工作,我会在执行后报告。

0


之所以甚至消除server.shutdown()是没有帮助,因为当主线程存在,服务器线程,因为你可能还没有删除server_thread.daemon=True立刻存在。
如果将其更改为server_thread.daemon=False,那么即使在主线程终止后,程序也不会立即返回到终端,但即使主程序的最后一行执行后,也不会终止服务器。
我不知道你是否可以使用简单的Python脚本完全在后台运行服务器,但我认为这是不可能的。

你可以用'&'选项调用脚本:python3 <file>.py &它将在后台运行python脚本(至少与Ubuntu一起工作)(https://askubuntu.com/questions/396654/how-to-run-the-python-program-in-the-background-in-ubuntu-machine),但它可能不是你正在寻找的答案。

+0

是不是我所希望的。本质上它是一个即时通讯程序,我已经看到了,但我不太确定他们是如何让客户端成为唯一必须开始的事情,而不是让每个客户端也成为服务器。程序的服务器部分负责收集和存储对操作至关重要的信息。 – user2763113

+0

我也尝试删除守护线(我忘了提到它),结果是服务器“熬夜”,但仍无法连接到。对于线程,我认为尽管理论上它应该是可能的,因为服务器将在其自己的线程上执行,而客户端在另一个线程上执行。 – user2763113