所以我已经制作了一些代码。假设让服务器和客户端进行通信......但它不起作用。
有人可以解释原因,或者更好地修复我的代码???
服务器。
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 :(得分: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()