无法连接到Python服务器
我刚开始学习在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 个回答
你已经设置了监听(listen(2)),现在你需要处理来自新连接的请求。
把
conn, addr = sock.accept() # accept connection
放在一个循环里。
你可以在一个进程里处理这个问题。
最简单的方法是一个一个地处理每个连接。也就是说,先等待并接受一个连接,然后和对方进行交流,最后再断开连接。接着再等下一个连接。不过,这种方法不适合你想要同时处理多个客户端连接的情况,显然也不够灵活。下面是你代码的一个修改版,可以处理串行连接:
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,不过它的学习曲线比较陡峭,可能对你的需求来说有点过于复杂。
这是因为你的'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和连接的概念,我相信这对你将来会有很大帮助。
希望这能帮到你。
祝好