无法连接到Python服务器

2 投票
3 回答
2401 浏览
提问于 2025-04-18 17:47

我刚开始学习在Python中使用套接字,所以我想创建一个简单的服务器:客户端可以连接并等待一段时间。

我遇到的问题是,当我从第一个客户端(client.py)连接到服务器时,服务器会记录这个连接,但当我同时从另一个客户端(比如平板的网页浏览器)连接到服务器时,服务器却没有记录这个连接。它没有给第二个客户端发送消息,就好像这个客户端不存在一样。但在我的代码中,我明明有写listen(2)

这是否意味着我必须为每个新的连接创建一个新的进程?将来我想创建一个非常简单的聊天程序(让很多人可以在一个聊天室里聊天,两个用户在一个房间里)来练习。或者我可以把客户端的连接信息收集到一个clients列表中,然后再为这两个人创建一个进程吗?

settings.py

number_of_connections = 2
host = ''
port = 9090

server.py

import time
from socket import socket, AF_INET, SOCK_STREAM
from multiprocessing import Process
from settings import host, port, number_of_connections

def logging(message):
        print(message)
        with open('log.txt', 'a') as f:
            f.write('%s\n' % message)

clients = []

sock = socket(AF_INET, SOCK_STREAM)

sock.bind((host, port))

sock.listen(number_of_connections)

conn, addr = sock.accept() # accept connection. conn - new socket, addr - client`s adress

clients.append((conn, addr))

#conn.settimeout(60)
logging('%s Connection from %s:%s' % (time.ctime(), addr[0], addr[1]))

while True:
    data = conn.recv(1024)
    if not data:
        break
    udata = data.decode("utf-8")
    logging("Server recieve Data: %s" % udata)
    #conn.send(data.upper())
    conn.send(b"Hello! From server!\n")
    conn.send(b"Your data: " + udata.encode("utf-8"))
    # if we had 2 clients, create process? 
    if len(clients) == 2:
        print(clients)
        clients.clear()

client.py

from socket import socket, AF_INET, SOCK_STREAM
from settings import host, port

sock = socket(AF_INET, SOCK_STREAM)
sock.connect((host, port))
sock.send(b'hello, world! From client')


while True:
    data = sock.recv(1024)

    print(data)

非常感谢!

3 个回答

0

你已经设置了监听(listen(2)),现在你需要处理来自新连接的请求。

conn, addr = sock.accept() # accept connection

放在一个循环里。

1

你可以在一个进程里处理这个问题。

最简单的方法是一个一个地处理每个连接。也就是说,先等待并接受一个连接,然后和对方进行交流,最后再断开连接。接着再等下一个连接。不过,这种方法不适合你想要同时处理多个客户端连接的情况,显然也不够灵活。下面是你代码的一个修改版,可以处理串行连接:

import time
from socket import socket, AF_INET, SOCK_STREAM
from multiprocessing import Process
from settings import host, port, number_of_connections

def logging(message):
        print(message)
        with open('log.txt', 'a') as f:
            f.write('%s\n' % message)

sock = socket(AF_INET, SOCK_STREAM)
sock.bind((host, port))
sock.listen(number_of_connections)

while True:
    logging("Waiting for connection on %s:%s" % (host, port))
    conn, addr = sock.accept()
    logging('%s Connection from %s:%s' % (time.ctime(), addr[0], addr[1]))

    while True:
        data = conn.recv(1024)
        if not data:
            # remote closed connection, close and wait for a new connection
            logging("Client closed connection")
            conn.close()
            break

        udata = data.decode("utf-8")
        logging("Server recieve Data: %s" % udata)
        #conn.send(data.upper())
        conn.send(b"Hello! From server!\n")
        conn.send(b"Your data: " + udata.encode("utf-8"))

但是,因为你实际上想要处理多个同时连接,所以现在需要看看 select模块,它提供了一些函数来帮助处理异步输入输出(可以看看 select() 和/或 poll() 函数)。还有 asyncore模块 也值得一看。asynchat 可能包含你需要的所有功能。

另一种选择是为每个客户端创建一个新的线程或子进程。

还有一个更复杂的选择是 twisted,不过它的学习曲线比较陡峭,可能对你的需求来说有点过于复杂。

3

这是因为你的'conn'变量是来自第一个连接到这个socket的客户端的连接。试着把你的脚本改成循环处理sock.accept()。

下面是你的server.py,做了很少的修改,这样你就能看到区别。

import time
from socket import socket, AF_INET, SOCK_STREAM
from multiprocessing import Process
from settings import host, port, number_of_connections

def logging(message):
        print(message)
        with open('log.txt', 'a') as f:
            f.write('%s\n' % message)

clients = []

sock = socket(AF_INET, SOCK_STREAM)

sock.bind((host, port))

sock.listen(number_of_connections)

while True:
    conn, addr = sock.accept()
    data = conn.recv(1024)
    if not data:
        break
    udata = data.decode("utf-8")
    logging("Server recieve Data: %s" % udata)
    conn.send(b"Hello! From server!\n")
    conn.send(b"Your data: " + udata.encode("utf-8"))

如果你想了解一个聊天服务器/客户端的例子,可以看看这个:

http://code.activestate.com/recipes/531824/

多了解一下socket和连接的概念,我相信这对你将来会有很大帮助。

希望这能帮到你。

祝好

撰写回答