为什么这个python套接字聊天服务器不能正常工作?

时间:2017-09-14 20:30:46

标签: python sockets

所以我已经制作了一些代码。假设让服务器和客户端进行通信......但它不起作用。

有人可以解释原因,或者更好地修复我的代码???

服务器。

import time
import socket
from threading import Thread

global sS
sS = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sS.bind(('', 2347))
sSconAddresses = []
sSconData = []
print(" Server : Running ... ")
sS.listen(10)

while True:
    try:
        cOn, aDr = sS.accept()
        sSconAddresses.insert(0, str(aDr))
        sSconData.insert(0, str(cOn))
        time.sleep(0.3)
    except:
        time.sleep(0.1)
        pass
def ConHandler():
    for _ in sSconData:
        PacketData = _.recv(700)
        if not PacketData:
            _.close()
        else:
            stringData = PacketData.decode('utf-8')
            print(stringData)
            sS.sendto(PacketData, _)
ConHandlerThread = Thread(target=ConHandler)
ConHandlerThread.daemon = True
ConHandlerThread.start()

客户端。

import threading, time
import socket, sys
import os

global cS
cS = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cS.connect(('PRIVATE', 2347))
Server = ('PRIVATE', 2347)


while True:
    PacketData = input(" Client> ")
    ByteData = PacketData.encode('utf-8')
    cS.sendto(ByteData, Server)

它不会返回任何错误,所以我很困惑为什么它不起作用。

1 个答案:

答案 0 :(得分:0)

首先,在你的服务器端代码中,你在开始你的线程之前有一段时间,所以它无法工作。

然后,如果您通过移动代码成功启动线程,它的for将看到一个空列表,因此它不会循环,只是在这里退出。

从您的代码开始,这是有效的方法:

客户:

import socket


def main():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('127.0.0.1', 2345))
    while True:
        packetdata = input(" Client> ")
        bytedata = packetdata.encode()
        client_socket.send(bytedata)
        print(client_socket.recv(700).decode())


if __name__ == '__main__':
    main()

服务器:

import socket
from threading import Thread
from queue import Queue


def client_handler(client_socket):
    while True:
        data = client_socket.recv(700)
        print(data)
        client_socket.send("Server {}".format(data.decode()).encode())


def conn_handler(conn_queue):
    while True:
        conn, address = conn_queue.get()
        print("Handler getting a connection from {}".format(address))
        client_thread = Thread(target=client_handler, args=(conn,))
        client_thread.daemon = True
        client_thread.start()


def main():
    print("Server: Running ...")
    conn_queue = Queue()
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('', 2345))
    server_socket.listen(10)


    con_handler_thread = Thread(target=conn_handler, args=(conn_queue,))
    con_handler_thread.daemon = True
    con_handler_thread.start()

    while True:
        conn_queue.put(server_socket.accept())


if __name__ == '__main__':
    main()

请注意,这不是最理想的,每个客户端启动一个线程的方式。处理这种情况的最佳方法是将所有内容保存在一个线程中,并使用类似select的函数来知道该怎么做。但是select也有点受限(比如最多1024个连接,在libc中硬编码),所以要使用epoll / kqueue /比poll / select更好的方法,并且有一个模块:https://docs.python.org/3/library/select.html

然而,使用选择模块仍然是用来表达您的需求的旧的,手动的,简洁的方式,您应该看看coroutine based API of asyncio,它能够以明确的方式表达意图。

asyncio等价物可能如下所示:

import asyncio


async def client():
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)

    while True:
        message = input("Client> ")
        writer.write(message.encode())
        data = await reader.read(100)
        print('Received: {}'.format(data.decode()))

loop = asyncio.get_event_loop()
loop.run_until_complete(client())

并且,服务器端:

import asyncio


async def handle_client(reader, writer):
    while True:
        data = await reader.read(100)
        if not data:
            return
        message = data.decode()
        addr = writer.get_extra_info('peername')
        print("Received %r from %r" % (message, addr))

        print("Send: %r" % message)
        writer.write(data)
        await writer.drain()


loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_client, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
print('Serving on {}'.format(server.sockets[0].getsockname()))
loop.run_forever()