创建多线程tcp服务器python 3

时间:2014-07-21 17:37:55

标签: python multithreading sockets

你好我试图创建一个同时接受多个客户端的简单服务器我是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()

3 个答案:

答案 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)