首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何保证使用python asyncio发送tcp数据?

如何保证使用python asyncio发送tcp数据?
EN

Stack Overflow用户
提问于 2014-10-02 04:37:02
回答 2查看 1.7K关注 0票数 1

我有一个客户端,连接到服务器并发送列表中的所有消息,每发送一条消息,它都会从列表中删除。

但是当我强制关闭服务器时,客户端仍然继续发送和删除列表中的消息。我希望如果连接断开,客户端停止发送消息,或者如果不能保证服务器已收到消息,则不要从列表中删除。

当我在连接断开后发送了四条以上的消息时,我检查是否显示错误"socket.send()引发异常“。但我不知道如何得到这个错误,我认为它是异步的。无论如何,如果我得到这个错误,如果列表在连接关闭后要发送的消息少于5条,则不会发生错误。

附言:我写的服务器只是为了我的测试,但服务器我将无法访问。所以,客户端需要做所有的事情来保证数据的发送。

非常感谢。

client.py

代码语言:javascript
复制
import asyncio

class Client(asyncio.Protocol):
    TIMEOUT = 1.0
    event_list = []
    for i in range(10):
        event_list.append('msg' + str(i))

    def __init__(self):
        self.client_tcp_timeout = None
        print(self.event_list)

    def connection_made(self, transport):
        print('Connected to Server.')
        self.transport = transport
        self.client_tcp_timeout = loop.call_later(self.TIMEOUT, self.send_from_call_later)

    def data_received(self, data):
        self.data = format(data.decode())
        print('data received: {}'.format(data.decode()))

    def send_from_call_later(self):
        self.msg = self.event_list[0].encode()
        self.transport.write(self.msg)
        print('data sent: {}'.format(self.msg))
        print('Removing data: {}'.format(self.event_list[0]))
        del self.event_list[0]
        print(self.event_list)
        print('-----------------------------------------')
        if len(self.event_list) > 0:
            self.client_tcp_timeout = loop.call_later(self.TIMEOUT, self.send_from_call_later)
        else:
            print('All list was sent to the server.')

    def connection_lost(self, exc):
        print('Connection lost!!!!!!.')

loop = asyncio.get_event_loop()

coro = loop.create_connection(Client, 'localhost', 8000)
client = loop.run_until_complete(coro)

loop.run_forever()

server.py

代码语言:javascript
复制
import asyncio

class Server(asyncio.Protocol):
    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        print('connection from {}'.format(peername))
        self.transport = transport

    def data_received(self, data):
        print('data received: {}'.format(data.decode()))
        #self.transport.write(data)

loop = asyncio.get_event_loop()
coro = loop.create_server(Server, 'localhost', 8000)
server = loop.run_until_complete(coro)

print('serving on {}'.format(server.sockets[0].getsockname()))

try:
    loop.run_forever()
except KeyboardInterrupt:
    print("exit")
finally:
    server.close()
    loop.close()

服务器输出(收到msg4后强制(CTRL+C)关闭服务器):

代码语言:javascript
复制
$ python3 server.py
serving on ('127.0.0.1', 8000)
connection from ('127.0.0.1', 56119)
data received: msg0
data received: msg1
data received: msg2
data received: msg3
data received: msg4
^Cexit

客户端输出

代码语言:javascript
复制
$ python3 client.py 
['msg0', 'msg1', 'msg2', 'msg3', 'msg4', 'msg5', 'msg6', 'msg7', 'msg8', 'msg9']
Connected to Server.
data sent: b'msg0'
Removing data: msg0
['msg1', 'msg2', 'msg3', 'msg4', 'msg5', 'msg6', 'msg7', 'msg8', 'msg9']
-----------------------------------------
data sent: b'msg1'
Removing data: msg1
['msg2', 'msg3', 'msg4', 'msg5', 'msg6', 'msg7', 'msg8', 'msg9']
-----------------------------------------
data sent: b'msg2'
Removing data: msg2
['msg3', 'msg4', 'msg5', 'msg6', 'msg7', 'msg8', 'msg9']
-----------------------------------------
data sent: b'msg3'
Removing data: msg3
['msg4', 'msg5', 'msg6', 'msg7', 'msg8', 'msg9']
-----------------------------------------
data sent: b'msg4'
Removing data: msg4
['msg5', 'msg6', 'msg7', 'msg8', 'msg9']
-----------------------------------------
Connection lost!!!!!!.
data sent: b'msg5'
Removing data: msg5
['msg6', 'msg7', 'msg8', 'msg9']
-----------------------------------------
data sent: b'msg6'
Removing data: msg6
['msg7', 'msg8', 'msg9']
-----------------------------------------
data sent: b'msg7'
Removing data: msg7
['msg8', 'msg9']
-----------------------------------------
data sent: b'msg8'
Removing data: msg8
['msg9']
-----------------------------------------
socket.send() raised exception.
data sent: b'msg9'
Removing data: msg9
[]
-----------------------------------------
All list was sent to the server.
EN

回答 2

Stack Overflow用户

发布于 2014-10-02 08:59:56

对TCP套接字的写入不能保证接收到数据。它只将数据发送到操作系统内核,然后操作系统内核将尽可能努力地将数据发送到另一端。但是,一旦数据被发送到操作系统内核,write调用就已经返回成功。如果数据随后被对等操作系统内核接收到,它将在TCP级别确认它们。但是,这只意味着数据是由内核接收的,而不是由应用程序处理的。

如果您想要有保证的消息传递并处理可能关闭的对等点,则必须在协议内部实现某种确认,并且仅在成功处理数据后从对等点应用程序获得显式确认后才删除数据。

票数 3
EN

Stack Overflow用户

发布于 2014-10-02 09:06:56

我希望如果连接断开,客户端停止发送消息,或者如果不能保证服务器已经收到消息,则不要从列表中删除。

因此,编写代码就可以做到这一点。在服务器指示它已收到消息之前,不要删除该消息。你可以以任何你喜欢的方式来实现它,但是如果它是你想要的行为,你就必须对它进行编码。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26150160

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档