Last active
October 22, 2017 13:13
-
-
Save krrr/8b5fec3c93dc332bc8109641206529b5 to your computer and use it in GitHub Desktop.
Windows 10 TCP fast open sample
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <WinSock2.h> | |
#include <MSWSock.h> | |
#include <WS2tcpip.h> | |
#pragma comment(lib, "Ws2_32.lib") | |
static LPFN_CONNECTEX ConnectEx = NULL; | |
static BOOL load_mswsock(void) { | |
/* Dummy socket needed for WSAIoctl */ | |
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); | |
if (sock == INVALID_SOCKET) | |
return FALSE; | |
GUID guid = WSAID_CONNECTEX; | |
DWORD dwBytes; | |
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, | |
&guid, sizeof(guid), | |
&ConnectEx, sizeof(ConnectEx), | |
&dwBytes, NULL, NULL) != 0) | |
return FALSE; | |
closesocket(sock); | |
return TRUE; | |
} | |
int main(int argc, char *argv[]) { | |
WSADATA wsaData; | |
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { | |
printf("WSAStartup failed"); | |
return 1; | |
} | |
if (!load_mswsock()) { | |
printf("Error loading mswsock functions: %d\n", WSAGetLastError()); | |
return 1; | |
} | |
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); | |
if (sock == INVALID_SOCKET) { | |
printf("socket: %d\n", WSAGetLastError()); | |
return 1; | |
} | |
char optVal = TRUE; | |
if (setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &optVal, sizeof(optVal)) != 0) { | |
printf("setsockopt failed: %d\n", WSAGetLastError()); | |
return 1; | |
} | |
/* ConnectEx requires the socket to be initially bound. */ | |
sockaddr_in addr; | |
ZeroMemory(&addr, sizeof(addr)); | |
addr.sin_family = AF_INET; | |
addr.sin_addr.s_addr = INADDR_ANY; | |
addr.sin_port = 0; | |
if (bind(sock, (SOCKADDR*) &addr, sizeof(addr)) != 0) { | |
printf("bind failed: %d\n", WSAGetLastError()); | |
return 1; | |
} | |
/* Issue ConnectEx and wait for the operation to complete. */ | |
OVERLAPPED ol; | |
ZeroMemory(&ol, sizeof(ol)); | |
// 198.35.26.96 en.wikipedia | |
inet_pton(AF_INET, "172.93.41.174", &addr.sin_addr.s_addr); | |
addr.sin_port = htons(80); | |
BYTE dat[] = "GET / HTTP/1.0\n\n"; | |
DWORD bytesSent; | |
BOOL ok = ConnectEx(sock, (SOCKADDR*) &addr, sizeof(addr), dat, sizeof(dat)-1, &bytesSent, &ol); | |
if (ok) { | |
printf("ConnectEx succeeded immediately\n"); | |
} else if (WSAGetLastError() == ERROR_IO_PENDING) { | |
ok = GetOverlappedResult((HANDLE) sock, &ol, &bytesSent, TRUE); | |
printf("ConnectEx pending\n"); | |
if (!ok) | |
printf("ConnectEx failed: %d\n", WSAGetLastError()); | |
} else { | |
printf("ConnectEx failed: %d\n", WSAGetLastError()); | |
return 1; | |
} | |
char buf[4096]; | |
recv(sock, buf, 4096, 0); | |
closesocket(sock); | |
WSACleanup(); | |
printf("Done\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
连维基百科的443端口成功几率挺大的
然而连我自己服务器的80端口经常出现莫名其妙的延时3秒才回http响应,还有相当大的几率SYN+PSH包丢掉,fallback到传统三次握手。
更让人心寒的是SoftEther VPN内嵌的NAT造成tfo的第一个包100%被丢,然后windows会自动禁用tfo。断开vpn也不会马上恢复
这破玩意儿根本不能用嘛