From b35f44c5524390a952d7d211c93e2cbe585acca2 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 02:05:39 +0100 Subject: [PATCH] Fix WebSocket sendFrame delay by enabling TCP_NODELAY (#5077) * Initial plan * Fix WebSocket sendFrame delay by enabling TCP_NODELAY - Enable TCP_NODELAY in WebSocketImpl constructor to prevent Nagle's algorithm from buffering small WebSocket frames - Add check to skip TCP_NODELAY for Unix domain sockets - Add documentation about TCP_NODELAY behavior to WebSocket class - Tested with existing WebSocket test suite - all tests pass Co-authored-by: aleks-f <2429093+aleks-f@users.noreply.github.com> * Address code review feedback - Avoid unnecessary SocketAddress object construction by calling family() directly - Use specific exception type (Poco::Exception) instead of catch-all Co-authored-by: aleks-f <2429093+aleks-f@users.noreply.github.com> * Refine exception handling for TCP_NODELAY configuration - Catch specific exception types (NetException, IOException, InvalidArgumentException) instead of broad Poco::Exception - Improve error handling comments for clarity Co-authored-by: aleks-f <2429093+aleks-f@users.noreply.github.com> * Consolidate exception handling for better maintainability - Combine catch blocks since all exceptions are handled identically - Improve code clarity with more descriptive comments Co-authored-by: aleks-f <2429093+aleks-f@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: aleks-f <2429093+aleks-f@users.noreply.github.com> --- Net/include/Poco/Net/WebSocket.h | 4 ++++ Net/src/WebSocketImpl.cpp | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Net/include/Poco/Net/WebSocket.h b/Net/include/Poco/Net/WebSocket.h index 8034ca248..d0af70f32 100644 --- a/Net/include/Poco/Net/WebSocket.h +++ b/Net/include/Poco/Net/WebSocket.h @@ -54,6 +54,10 @@ class Net_API WebSocket: public StreamSocket /// mode, by calling setBlocking(false). /// Please refer to the sendFrame() and receiveFrame() documentation /// for non-blocking behavior. + /// + /// TCP_NODELAY is automatically enabled on the underlying socket + /// to prevent delays from Nagle's algorithm when sending small + /// WebSocket frames. { public: enum Mode diff --git a/Net/src/WebSocketImpl.cpp b/Net/src/WebSocketImpl.cpp index 64873cd28..795c6c706 100644 --- a/Net/src/WebSocketImpl.cpp +++ b/Net/src/WebSocketImpl.cpp @@ -18,6 +18,7 @@ #include "Poco/Net/NetException.h" #include "Poco/Net/WebSocket.h" #include "Poco/Net/HTTPSession.h" +#include "Poco/Net/SocketAddress.h" #include "Poco/Buffer.h" #include "Poco/BinaryWriter.h" #include "Poco/BinaryReader.h" @@ -42,6 +43,21 @@ WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& s poco_check_ptr(pStreamSocketImpl); _pStreamSocketImpl->duplicate(); session.drainBuffer(_buffer); + // Enable TCP_NODELAY to prevent delays caused by Nagle's algorithm + // for small WebSocket frames. Skip for Unix domain sockets. + try + { + if (_pStreamSocketImpl->address().family() != SocketAddress::UNIX_LOCAL) + _pStreamSocketImpl->setNoDelay(true); + } + catch (NetException&) + { + // Ignore - socket errors (e.g., not connected or doesn't support TCP options) + } + catch (Poco::Exception&) + { + // Ignore - other configuration errors (IOException, InvalidArgumentException, etc.) + } }