你好我试图创建一个同时接受多个客户端的简单服务器我是python的新手,我很难理解它....我尝试在多线程应用程序中更改我的代码但没有正面结果。 ..代码是:
import socket, threading
def message():
while 1:
data = connection.recv(1024)
if not data: break
#connection.sendall(b'-- Message Received --\n')
print(data.decode('utf-8'))
connection.close()
def connection():
address = input("Insert server ip")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
def accept connection():
connection, address = s.accept()
print('Client connected with address:', address)
t=thread.Threading(target=message,args=(connection))
t.run()
我知道有很多错误,但我是python中的新手抱歉:(
原始的非线程代码是:
import socket
address = input("Insert server ip:")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
connection, address = s.accept()
print('Client connected with address:', address)
while 1:
data = connection.recv(1024)
if not data: break
#connection.sendall(b'-- Message Received --\n')
print(data.decode('utf-8'))
connection.close()
答案 0 :(得分:2)
你的基本设计很接近,但是你有很多小问题让你很难前进。
首先,您有一个带有空格的函数名称,这是不允许的。你有一个IndentationError
,因为你没有缩进它的内容。
接下来,在accept_connection
功能中,您使用了threading
错误。
thread.Threading
不存在;你可能意味着threading.Thread
。
args
必须是值的序列(元组,列表等)。您可能希望(connection)
是一个值的元组,但它不是;元组是用逗号定义的,而不是括号,你所拥有的只是值connection
,周围有多余的括号。你想在这里(connection,)
。
此外,在线程对象上调用run
只会在当前线程中运行线程的代码。您想调用start
,它将启动一个新线程并在该线程上调用run
方法。
与此同时,您实际上从未在任何地方实际调用此功能,因此它当然无法做任何事情。想想你想把它叫做什么。创建侦听器套接字后,您希望循环accept
,为每个接受的连接启动一个新的客户端线程,对吧?因此,您希望在connection
内部或顶级(在这种情况下connection
必须return s
)循环调用它。
最后,您的accept_connection
函数无法从其他函数访问局部变量;如果您希望它使用名为s
的套接字,则必须将其作为参数传递。
所以:
def connection():
address = input("Insert server ip")
port = 44444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.listen(1)
print("Server started! Waiting for connections...")
while True:
accept_connection(s)
def accept_connection(s):
connection, address = s.accept()
print('Client connected with address:', address)
t=thread.Threading(target=message, args=(connection,))
t.start()
作为旁注,请谨慎使用sock.recv(1024)
,并假设您将获得另一方发送send(msg)
的整条消息。你可能得到它,或者你可能得到消息的一半,或整个消息加上客户端稍后发送的另一条消息的一半。套接字只是字节流,如文件,而不是单独的消息流;你需要某种协议来分隔信息。
最简单的协议是在每条线路上发送每条消息。然后你就可以socket.makefile()
和for line in f:
,就像你真实的文件一样。当然,如果你的消息可以有换行符,那么这不起作用,但是你可以,例如,反斜杠 - 一方面逃避它们,另一方面转移它们。
答案 1 :(得分:1)
这是一篇很老的文章,但是有一种很好的方法可以完成您所谈论的事情。这是我不久前发布的示例的链接:
https://bitbucket.org/matthewwachter/tcp_threadedserver/src/master/
和脚本:
from datetime import datetime
from json import loads, dumps
from pprint import pprint
import socket
from threading import Thread
class ThreadedServer(Thread):
def __init__(self, host, port, timeout=60, debug=False):
self.host = host
self.port = port
self.timeout = timeout
self.debug = debug
Thread.__init__(self)
# run by the Thread object
def run(self):
if self.debug:
print(datetime.now())
print('SERVER Starting...', '\n')
self.listen()
def listen(self):
# create an instance of socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# bind the socket to its host and port
self.sock.bind((self.host, self.port))
if self.debug:
print(datetime.now())
print('SERVER Socket Bound', self.host, self.port, '\n')
# start listening for a client
self.sock.listen(5)
if self.debug:
print(datetime.now())
print('SERVER Listening...', '\n')
while True:
# get the client object and address
client, address = self.sock.accept()
# set a timeout
client.settimeout(self.timeout)
if self.debug:
print(datetime.now())
print('CLIENT Connected:', client, '\n')
# start a thread to listen to the client
Thread(target = self.listenToClient,args = (client,address)).start()
# send the client a connection message
# res = {
# 'cmd': 'connected',
# }
# response = dumps(res)
# client.send(response.encode('utf-8'))
def listenToClient(self, client, address):
# set a buffer size ( could be 2048 or 4096 / power of 2 )
size = 1024
while True:
try:
# try to receive data from the client
data = client.recv(size).decode('utf-8')
if data:
data = loads(data.rstrip('\0'))
if self.debug:
print(datetime.now())
print('CLIENT Data Received', client)
print('Data:')
pprint(data, width=1)
print('\n')
#send a response back to the client
res = {
'cmd': data['cmd'],
'data': data['data']
}
response = dumps(res)
client.send(response.encode('utf-8'))
else:
raise error('Client disconnected')
except:
if self.debug:
print(datetime.now())
print('CLIENT Disconnected:', client, '\n')
client.close()
return False
if __name__ == "__main__":
ThreadedServer('127.0.0.1', 8008, timeout=86400, debug=True).start()
答案 2 :(得分:0)
以下是我展示了一个线程套接字连接的示例代码。
def sock_connection( sock, host ):
"Handle socket"
pass
while 1:
try:
newsock = sock.accept()
thread = Thread( target=sock_connection, args=newsock )
thread.start()
except Exception, e:
print "error on socket connection: " % e)