I notice that HAProxy's probing mechanism is like:
Client -> [SYN] -> Server
Client <- [ACK/SYN] <- Server
Client -> [ACK/RST] -> Server
After browsing the source codes of HAProxy, I think they are not modifying the network stack behavior and achieve that in user-mode. So I guess that's a trick of socket options. Could you please give me some hints of it?
I replicated described behavior with TCP Fast Open. When connect()
is used, TCP client(who you marked as Server) will wait for SYN-ACK and reply with ACK.
Here is my example:
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sai;
sai.sin_family = AF_INET;
sai.sin_port = htons(1234);
sai.sin_addr.s_addr = inet_addr("127.0.0.1");
struct linger sl;
sl.l_onoff = 1; /* non-zero value enables linger option in kernel */
sl.l_linger = 0; /* timeout interval in seconds */
setsockopt(sock, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
int ret = sendto(sock, NULL, 0, MSG_FASTOPEN | MSG_MORE, &sai, sizeof(sai));
if(ret == -1) {
//Probing or TFO failed
//If TFO failed, try connect()
}
close(sock);
}