[ create a new paste ] login | about

Link: http://codepad.org/Ebx7b1XG    [ raw code | fork | 1 comment ]

ultramage - C++, pasted on Sep 30:
// windows: cl sockettest.cpp ws2_32.lib /Ox
// freebsd: g++ sockettest.cpp -o sockettest -O3

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#else
#include <sys/socket.h>
#include <netinet/in.h> //IPPROTO_TCP
#include <netdb.h> //getaddrinfo()
#include <unistd.h> //close()
#include <sys/time.h> //timeval, gettimeofday()
#define SOCKET int
#define SOCKET_ERROR (-1)
#define closesocket(x) close(x)
#endif
#include <stdio.h> //NULL, printf()
#include <string.h> //memset()
#include <math.h> //pow()


#ifdef _WIN32
class WSAHelper
{
public:
	WSAHelper()
	{ 
		WSAData data;
		WSAStartup(MAKEWORD(2,2), &data);
	}

	~WSAHelper()
	{
		WSACleanup();
	}
};
WSAHelper g_wsah;
#endif


unsigned int tick(void)
{
#ifdef _WIN32
	return GetTickCount();
#else
	struct timeval tval;
	gettimeofday(&tval, NULL);
	return tval.tv_sec * 1000 + tval.tv_usec / 1000;
#endif
}


// use netcat on server side
// nc -l -k 5555 > /dev/null
const char* server = "example.org";
const char* port = "5555";
int nIterations = 8;
int nSends = 2048;
int nBytes = 512;


int main(int argc, char* argv[])
{
	if( argc > 2 )
	{
		server = argv[1];
		port = argv[2];
	}

	// just for informative purposes	
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	int default_bufsize;
	socklen_t slen = sizeof(default_bufsize);
	int ret2 = getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&default_bufsize, &slen);
	printf("Default send buffer size is %d.\n", default_bufsize);
	closesocket(s);

	for( int r = 0; r < nIterations; ++r )
	{                  
	printf("Iteration %d...", r);
	scanf("%*c");

	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	int bufsize = 8192 * pow(2,(float)r);
	int ret1 = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(bufsize));

	struct linger l;
	l.l_onoff = 1; // enabled
	l.l_linger = 10; // seconds
	setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l));

	addrinfo* ai;
	getaddrinfo(server, port, NULL, &ai);

	connect(s, ai->ai_addr, ai->ai_addrlen);

	char* buf = new char[nBytes];
	memset(buf, '\0', nBytes);

	time_t start = tick();

	for( int i = 0; i < nSends; ++i )
		send(s, buf, nBytes, 0);

	closesocket(s);

	time_t end = tick();

	delete[] buf;

	printf("%d bytes at %d bufsize in %d ms.\n", nSends*nBytes, bufsize, end-start);

	}

	return 0;
}


Create a new paste based on this one


Comments:
posted by ultramage on Sep 30
So it turns out that on Windows, you need to up the send buffer size to achieve an efficient tcp stream that does not have tons of small fragmented packets and utilizes the sliding window algorithm. In my test, 256KB was the minimum.

On freebsd, it doesn't matter what you do, the stream does not fragment at all.
reply