From 168e851cce38e1ca0fcb47a5b46a4d612f76d848 Mon Sep 17 00:00:00 2001 From: Wenhai Lin Date: Thu, 31 Dec 2015 10:42:06 +0800 Subject: [PATCH] Fixed WebSocket may automatically disconnected if invoke `send` several times in quick succession on Android. --- cocos/network/WebSocket.cpp | 17 +++++------ .../NetworkTest/WebSocketTest.cpp | 29 ++++++++++++++++++- .../NetworkTest/WebSocketTest.h | 1 + 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/cocos/network/WebSocket.cpp b/cocos/network/WebSocket.cpp index 6695986dbe..1d301c329b 100644 --- a/cocos/network/WebSocket.cpp +++ b/cocos/network/WebSocket.cpp @@ -530,10 +530,11 @@ int WebSocket::onSocketCallback(struct libwebsocket_context *ctx, std::lock_guard lk(_wsHelper->_subThreadWsMessageQueueMutex); - std::list::iterator iter = _wsHelper->_subThreadWsMessageQueue->begin(); + auto iter = _wsHelper->_subThreadWsMessageQueue->begin(); - int bytesWrite = 0; - for (; iter != _wsHelper->_subThreadWsMessageQueue->end();) + //To avoid automatically disconnected on Android,send only one WsMessage at a time. + //for (; iter != _wsHelper->_subThreadWsMessageQueue->end();) + if (iter != _wsHelper->_subThreadWsMessageQueue->end()) { WsMessage* subThreadMsg = *iter; @@ -546,8 +547,6 @@ int WebSocket::onSocketCallback(struct libwebsocket_context *ctx, size_t remaining = data->len - data->issued; size_t n = std::min(remaining, c_bufferSize ); - //fixme: the log is not thread safe -// CCLOG("[websocket:send] total: %d, sent: %d, remaining: %d, buffer size: %d", static_cast(data->len), static_cast(data->issued), static_cast(remaining), static_cast(n)); unsigned char* buf = new unsigned char[LWS_SEND_BUFFER_PRE_PADDING + n + LWS_SEND_BUFFER_POST_PADDING]; @@ -576,20 +575,18 @@ int WebSocket::onSocketCallback(struct libwebsocket_context *ctx, writeProtocol |= LWS_WRITE_NO_FIN; } - bytesWrite = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], n, (libwebsocket_write_protocol)writeProtocol); - //fixme: the log is not thread safe -// CCLOG("[websocket:send] bytesWrite => %d", bytesWrite); + auto bytesWrite = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], n, (libwebsocket_write_protocol)writeProtocol); // Buffer overrun? if (bytesWrite < 0) { - break; + //break; } // Do we have another fragments to send? else if (remaining != n) { data->issued += n; - break; + //break; } // Safely done! else diff --git a/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp b/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp index be8cc6a01f..9f616679ea 100644 --- a/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp +++ b/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp @@ -34,10 +34,15 @@ WebSocketTest::WebSocketTest() itemSendText->setPosition(Vec2(winSize.width / 2, winSize.height - MARGIN - SPACE)); menuRequest->addChild(itemSendText); + labelSendText = Label::createWithTTF("Send Multiple Text", "fonts/arial.ttf", 20); + itemSendText = MenuItemLabel::create(labelSendText, CC_CALLBACK_1(WebSocketTest::onMenuSendMultipleTextClicked, this)); + itemSendText->setPosition(Vec2(winSize.width / 2, winSize.height - MARGIN - 2 * SPACE)); + menuRequest->addChild(itemSendText); + // Send Binary auto labelSendBinary = Label::createWithTTF("Send Binary", "fonts/arial.ttf", 20); auto itemSendBinary = MenuItemLabel::create(labelSendBinary, CC_CALLBACK_1(WebSocketTest::onMenuSendBinaryClicked, this)); - itemSendBinary->setPosition(Vec2(winSize.width / 2, winSize.height - MARGIN - 2 * SPACE)); + itemSendBinary->setPosition(Vec2(winSize.width / 2, winSize.height - MARGIN - 3 * SPACE)); menuRequest->addChild(itemSendBinary); @@ -210,6 +215,28 @@ void WebSocketTest::onMenuSendTextClicked(cocos2d::Ref *sender) } } +void WebSocketTest::onMenuSendMultipleTextClicked(cocos2d::Ref *sender) +{ + if (! _wsiSendText) + { + return; + } + + if (_wsiSendText->getReadyState() == network::WebSocket::State::OPEN) + { + _sendTextStatus->setString("Send Multiple Text WS is waiting..."); + for (int index = 0; index < 15; ++index) { + _wsiSendText->send(StringUtils::format("Hello WebSocket, text message index:%d", index)); + } + } + else + { + std::string warningStr = "send text websocket instance wasn't ready..."; + log("%s", warningStr.c_str()); + _sendTextStatus->setString(warningStr.c_str()); + } +} + void WebSocketTest::onMenuSendBinaryClicked(cocos2d::Ref *sender) { if (! _wsiSendBinary) { diff --git a/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.h b/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.h index 5385337cf0..e478cd32e2 100644 --- a/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.h +++ b/tests/cpp-tests/Classes/ExtensionsTest/NetworkTest/WebSocketTest.h @@ -32,6 +32,7 @@ public: // Menu Callbacks void onMenuSendTextClicked(cocos2d::Ref *sender); + void onMenuSendMultipleTextClicked(cocos2d::Ref *sender); void onMenuSendBinaryClicked(cocos2d::Ref *sender); virtual std::string title() const override { return "WebSocket Test"; }