Skip to content

Commit c52ca2e

Browse files
author
vis2k
committed
Server: option to maximize send/receive buffers to OS limit
1 parent 19301ec commit c52ca2e

1 file changed

Lines changed: 42 additions & 4 deletions

File tree

kcp2k/Assets/kcp2k/highlevel/KcpServer.cs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public class KcpServer
1818
// DualMode uses both IPv6 and IPv4. not all platforms support it.
1919
// (Nintendo Switch, etc.)
2020
public bool DualMode;
21+
// too small send/receive buffers might cause connection drops under
22+
// heavy load. using the OS max size can make a difference already.
23+
public bool MaximizeSendReceiveBuffersToOSLimit = true;
2124

2225
// kcp configuration
2326
// NoDelay is recommended to reduce latency. This also scales better
@@ -94,6 +97,43 @@ public KcpServer(Action<int> OnConnected,
9497

9598
public bool IsActive() => socket != null;
9699

100+
// if connections drop under heavy load, increase to OS limit.
101+
// if still not enough, increase the OS limit.
102+
void ConfigureSocketBufferSizes()
103+
{
104+
if (MaximizeSendReceiveBuffersToOSLimit)
105+
{
106+
// log initial size for comparison.
107+
// remember initial size for log comparison
108+
int initialReceive = socket.ReceiveBufferSize;
109+
int initialSend = socket.SendBufferSize;
110+
111+
// 100k attempts of 1 KB increases = default + 100 MB max
112+
const int attempts = 100_000;
113+
const int increase = 1024;
114+
115+
// setting a too large size throws a socket exception.
116+
// so let's keep increasing until we encounter it.
117+
for (int i = 0; i < attempts; ++i)
118+
{
119+
// increase in 1 KB steps
120+
try { socket.ReceiveBufferSize += increase; }
121+
catch (SocketException) { break; }
122+
}
123+
124+
for (int i = 0; i < attempts; ++i)
125+
{
126+
// increase in 1 KB steps
127+
try { socket.SendBufferSize += increase; }
128+
catch (SocketException) { break; }
129+
}
130+
131+
Log.Info($"KcpServer: RecvBuf = {initialReceive}=>{socket.ReceiveBufferSize} ({socket.ReceiveBufferSize/initialReceive}x) SendBuf = {initialSend}=>{socket.SendBufferSize} ({socket.SendBufferSize/initialSend}x) increased to OS limits!");
132+
}
133+
// otherwise still log the defaults for info.
134+
else Log.Info($"KcpServer: RecvBuf = {socket.ReceiveBufferSize} SendBuf = {socket.SendBufferSize}. If connections drop under heavy load, enable {nameof(MaximizeSendReceiveBuffersToOSLimit)} to increase it to OS limit. If they still drop, increase the OS limit.");
135+
}
136+
97137
public void Start(ushort port)
98138
{
99139
// only start once
@@ -117,10 +157,8 @@ public void Start(ushort port)
117157
socket.Bind(new IPEndPoint(IPAddress.Any, port));
118158
}
119159

120-
// show socket buffer size.
121-
// if connections drop under heavy load, increase to OS limit.
122-
// if still not enough, increase the OS limit.
123-
Log.Info($"KcpServer: RecvBuf = {socket.ReceiveBufferSize} SendBuf = {socket.SendBufferSize}. If connections drop under heavy load, increase to OS limit. If they still drop, increase the OS limit.");
160+
// configure socket buffer size.
161+
ConfigureSocketBufferSizes();
124162
}
125163

126164
public void Send(int connectionId, ArraySegment<byte> segment, KcpChannel channel)

0 commit comments

Comments
 (0)