gpt4 book ai didi

Python TCP 服务器,写入客户端?

转载 作者:太空宇宙 更新时间:2023-11-03 19:37:05 24 4
gpt4 key购买 nike

我有一个 tcp 服务器,它使用 select 调用来多路复用来自客户端的读取。我有一个客户端类(MClient),它管理传入数据包的解码

while(1)

rlist, wlist, xlist = select( input_sockets, output_sockets, [] , 1)

for insock in rlist: #any clients????

if insock is server_socket:
new_socket, addr = server_socket.accept()
input_sockets.append(new_socket)
clients[insock.fileno()] = MClient(new_socket, addr, client_id) #dict of clients
else:
data = insock.recv(512)
if data:
clients[insock.fileno()].ProcessPacket(data)
else:
input_sockets.remove(insock)
del clients[insock.fileno()]

#handle writing to sockets
for outsock in wlist:
....not done yet



#do some other stuff not associated with the socket

我对如何处理将数据发送回客户端感到困惑,即如何写入列表“output_sockets”。我正在考虑在 MClient 对象中设置一个标志,表明我有数据要发送回客户端。然后,我将在服务器循环中检查每个客户端以查看是否设置了此标志,然后使用相应的套接字填充output_list。当套接字可用于写入时,我将调用适当的客户端写入函数。

这个方案看起来不太优雅,我想在主服务器循环中处理写入。我该如何实现这个目标?

谢谢

最佳答案

这是我不久前写的一些内容,旨在了解如何使用单个线程处理多个连接。它绝不是完美的,但说明了您想要做什么。客户端对象管理连接的读写流,并确保服务器在正确的 select() 列表中拥有客户端套接字。这实现了一个简单的协议(protocol),其中消息由换行符终止。 PumpXXXX() 函数只是阻止读/写流并管理读/写缓冲区。仅当在缓冲区中找到换行符时才会处理完整消息。

import socket
import select

class Client(object):

'''This object is created for each client connection. It tracks
what has been read, what has been written, and processes complete
messages terminated by newlines. It responds by returning the
original message wrapped in square brackets and terminated by a
newline. '''

def __init__(self,who,sock,server):

'''who - client address
sock - client socket
server - server object for this client
'''

self.who = who
self.readbuf = ''
self.writbuf = ''
self.server = server
self.sock = sock

def close(self):

'''Removes client from server's reader/writer queues and
closes the connection.'''

self.sock.close()
if self.sock in self.server.readers:
self.server.readers.remove(self.sock)
if self.sock in self.server.writers:
self.server.writers.remove(self.sock)
self.server.data.pop(self.sock)

def pumprecv(self):

'''Server calls pumprecv() when something is readable from the
client socket. The data is appended to the client's read
buffer.mro Complete messages (if any) are then removed from
the buffer and processed.'''

try:
tmp = self.sock.recv(1000)
except socket.error,e:
print 'recv',e
self.close()
else:
if tmp:
self.readbuf += tmp

# Complete messages are processed
while '\n' in self.readbuf:
msg,self.readbuf = self.readbuf.split('\n',1)
print self.who,msg
self.writbuf += '[' + msg + ']\n'
# New data to send. Make sure client is in the
# server's writer queue.
if self.sock not in self.server.writers:
self.server.writers.append(self.sock)
else:
self.close()

def pumpsend(self):
try:
# send some data. tmp is #chars sent (may not be all in writbuf).
tmp = self.sock.send(self.writbuf)
except socket.error,e:
print 'send:',e
self.close()
else:
# Removed sent characters from writbuf.
self.writbuf = self.writbuf[tmp:]
# If writbuf is empty, remove socket from server's write queue.
if not self.writbuf:
self.server.writers.remove(self.sock)

class Server(object):
def __init__(self,ip='127.0.0.1',port=9999):
self.ssock = socket.socket()
self.ssock.bind((ip,port))
self.ssock.listen(5)
self.readers = [self.ssock]
self.data = {}
self.writers = []
self.quit = False

def pumpaccept(self):

'''Called when server socket is readable to accept a
connection and create a Client object.'''

csock,who = self.ssock.accept()
print 'Connected %s:%d' % who
self.readers.append(csock)
self.data[csock] = Client(who,csock,self)

def serve(self):
while not self.quit or self.writers:
readable,writable,other = select.select(self.readers,self.writers,[],1.0)
# Operate on copies of the queues since the pumpXXX() commands can modify the lists.
if self.ssock in readable[:]:
self.pumpaccept()
readable.remove(self.ssock)
for reader in readable[:]:
self.data[reader].pumprecv()
for writer in writable[:]:
self.data[writer].pumpsend()

if not readable and not writable and not other:
print '.',

if __name__ == '__main__':
srv = Server()
srv.serve()

我通过在一个控制台中启动服务器并在其他控制台中运行以下代码来测试多个连接来对此进行测试。建立多个连接,从不同窗口交替发送,并发送部分消息以查看服务器如何响应。

>>> from socket import *
>>> s=socket()
>>> s.connect(('localhost',9999))
>>> s.send('one\ntwo\nthree')
13
>>> s.send('\nfour\n')
6
>>> s.recv(1024)
'[one]\n[two\three]\n[four]\n'
>>> s.close()

输出应类似于:

. . . . . . . . . . . . . . . . . . . Connected 127.0.0.1:1514
. . . . . . . . . ('127.0.0.1', 1514) one
. . . . . . . ('127.0.0.1', 1514) two
. . . ('127.0.0.1', 1514) three
('127.0.0.1', 1514) four
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

关于Python TCP 服务器,写入客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3043394/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com