Chapter 8: Raw TCP
This chapter describes TCP byte-stream semantics and explicit framing for custom protocols.
1. TCP has no message boundaries
TCP is an ordered byte stream. One send may be split across receives, and multiple sends may be merged. TcpInformation::data is the current received chunk, not necessarily one application message.
A real custom protocol needs framing: fixed size, length prefix, delimiter, or an explicit state machine.
2. Minimal echo demo
#include <sttnet.h>
#include <iostream>
class EchoTcpServer final : public stt::network::TcpServer
{
protected:
// TcpServer leaves heartbeat policy to derived protocols.
// This byte-echo demo does not need application-level heartbeat.
void handleHeartbeat() override {}
};
int main()
{
using namespace stt::network;
using stt::system::ServerSetting;
if(!ServerSetting::blockTerminationSignals())
return 1;
EchoTcpServer server;
// Raw TCP is a byte stream: one callback is one received chunk, not
// necessarily one complete application message. Real protocols add
// framing such as a fixed header, a length prefix, or a delimiter.
server.setGlobalSolveFunction(
[](TcpFDHandler &client, TcpInformation &info) {
// In a server callback, sendData() submits bytes to the bounded
// Reactor write queue; it does not block on the peer's network.
return client.sendData(info.data) > 0;
});
if(!server.startListen(6060))
{
std::cerr << "failed to listen on port 6060\n";
return 2;
}
std::cout << "TCP echo listening on 127.0.0.1:6060\n";
ServerSetting::waitForTerminationSignal();
return server.close() ? 0 : 3;
}3. Routing raw data
The default TCP key is the current data. setGlobalSolveFunction() handles arbitrary payloads; command- or length-based routing can parse a header in setGetKeyFunction() and store the key in info.ctx["key"].
4. Length-prefix parser outline
// 1. Append new bytes to a per-connection buffer.
// 2. Wait until at least four length bytes exist.
// 3. Decode and validate the payload length.
// 4. Wait until 4 + length bytes are buffered.
// 5. Extract one message and loop because one read may contain many.5. Test
./build/examples/sttnet_tcp_echo
printf 'hello TCP' | nc 127.0.0.1 6060