2017-09-14 60 views
-1

所以我做了一些代碼如下。它假設讓服務器和客戶端進行通信......但它不起作用。爲什麼這個python套接字聊天服務器不能正常工作?

有人可以解釋爲什麼,或更好地修復我的代碼?

服務器。

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) 

它不會返回任何錯誤,所以我很困惑它爲什麼不起作用。

回答

0

首先,在您的服務器端代碼中,在啓動線程之前您有一段時間的True,所以它無法工作。

然後,如果您通過移動代碼成功啓動線程,則其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也有點太有限(例如最多1024個連接,在libc中硬編碼),所以要走的路是使用epoll/kqueue /比輪詢/ 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() 
+0

感謝您的解釋。 – MAXBD

相關問題