<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: winsock code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Sun, 27 Jul 2008 03:28:14 GMT</pubDate>
    <description>DZone Snippets: winsock code</description>
    <item>
      <title>Windows socket demo program -- uses threads and stuff -- for stress testing the TCP stack</title>
      <link>http://snippets.dzone.com/posts/show/2471</link>
      <description>// I wrote this to find out if the claims made at http://laurentszyster.be/blog/tcp-stack-flaking-out/ is &lt;br /&gt;// valid.  I disagree with the opinions of the person who posted that TCP flakes out on Windows. I think&lt;br /&gt;// his program has obvious bugs.  This program proves that as long as you write your code properly&lt;br /&gt;// the TCP connections do not break randomly. Similar bugs existed in Bittorrent apparently, and they fixed them.&lt;br /&gt;// For more information visit http://sparebandwidth.blogspot.com/2006/08/more-on-tcp-flaking-out.html&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#define BUFFER_SIZE 1000&lt;br /&gt;#define SERVER_ADDR "127.0.0.1"&lt;br /&gt;#define SERVER_PORT 9999&lt;br /&gt;#define NUM_THREADS 1000&lt;br /&gt;#define SEND_SOCK_BUFFER_SIZE 34000&lt;br /&gt;#define RECV_SOCK_BUFFER_SIZE  34000&lt;br /&gt;#define SERVER_RECV_SOCK_BUFFER_SIZE  34000&lt;br /&gt;#define SERVER_SEND_SOCK_BUFFER_SIZE 34000&lt;br /&gt;#define CLIENT_LIMIT 1000	/* how many times to send/recv in client */&lt;br /&gt;&lt;br /&gt;#include &lt;stdio.h&gt;     &lt;br /&gt;#define FD_SETSIZE  NUM_THREADS&lt;br /&gt;#include &lt;winsock.h&gt;   &lt;br /&gt;#include &lt;stdlib.h&gt;    &lt;br /&gt;&lt;br /&gt;#define fatal_error(arg) {\&lt;br /&gt;		fprintf(stderr,"total in %d out %d, %s: %d\n",		\&lt;br /&gt;			total_bytes_received, total_bytes_sent,		\&lt;br /&gt;			arg, WSAGetLastError()); fflush(stderr); exit(1); }&lt;br /&gt;#define fatal_error2(arg)  { fprintf(stderr, "%s", arg); fflush(stderr); exit(1);}&lt;br /&gt;&lt;br /&gt;int threads_all_done = 0;&lt;br /&gt;&lt;br /&gt;struct thread_args {&lt;br /&gt;	int id;&lt;br /&gt;	int server_sock;&lt;br /&gt;	struct sockaddr_in server_addr;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void *client_thread(void *args)&lt;br /&gt;{&lt;br /&gt;	struct thread_args *client_thread_arg;&lt;br /&gt;	struct sockaddr_in server_addr;&lt;br /&gt;	int server_sock;&lt;br /&gt;	int client_sock;&lt;br /&gt;	int on = 1;&lt;br /&gt;	int bytes_received, bytes_sent;&lt;br /&gt;	int num_to_read;&lt;br /&gt;	int total_bytes_received, total_bytes_sent;&lt;br /&gt;	char buffer[BUFFER_SIZE];&lt;br /&gt;	int size;&lt;br /&gt;	int i;&lt;br /&gt;&lt;br /&gt;	total_bytes_received = total_bytes_sent = 0;&lt;br /&gt;	&lt;br /&gt;	client_thread_arg = (struct thread_args *)args;&lt;br /&gt;	memcpy(&amp;server_addr, &amp;client_thread_arg-&gt;server_addr,&lt;br /&gt;	       sizeof(struct sockaddr_in));&lt;br /&gt;	server_sock = client_thread_arg-&gt;server_sock;&lt;br /&gt;&lt;br /&gt;	if ((client_sock = socket(PF_INET, SOCK_STREAM,&lt;br /&gt;				  IPPROTO_TCP)) &lt; 0)&lt;br /&gt;		fatal_error("socket() error in client thread");&lt;br /&gt;&lt;br /&gt;	if (connect(client_sock, (struct sockaddr *)&amp;server_addr,&lt;br /&gt;		    sizeof(server_addr)) &lt; 0)&lt;br /&gt;		fatal_error("connect() error in client thread");&lt;br /&gt;&lt;br /&gt;	/* wait for the server to send startup message */&lt;br /&gt;	if ((bytes_received =&lt;br /&gt;	     recv(client_sock, buffer, BUFFER_SIZE, 0)) &lt; 0)&lt;br /&gt;		fatal_error("recv() error in client thread");&lt;br /&gt;&lt;br /&gt;	if (ioctlsocket(client_sock, FIONBIO, &amp;on) &lt; 0)&lt;br /&gt;		fatal_error("FIONBIO error in client thread");&lt;br /&gt;&lt;br /&gt;	size = SEND_SOCK_BUFFER_SIZE;&lt;br /&gt;	if (setsockopt(client_sock, SOL_SOCKET, SO_SNDBUF, &amp;size, sizeof(size)) &lt; 0)&lt;br /&gt;		fatal_error("SO_SNDBUF error in client thread");&lt;br /&gt;	size = RECV_SOCK_BUFFER_SIZE;&lt;br /&gt;	if (setsockopt(client_sock, SOL_SOCKET, SO_RCVBUF, &amp;size, sizeof(size)) &lt; 0)&lt;br /&gt;		fatal_error("SO_RCVBUF error in client thread");&lt;br /&gt;	&lt;br /&gt;	for (i = 0; i &lt; CLIENT_LIMIT ; i++) {&lt;br /&gt;		int errno;&lt;br /&gt;		&lt;br /&gt;		if ((bytes_sent =&lt;br /&gt;		     send(client_sock, buffer,&lt;br /&gt;			  BUFFER_SIZE, 0)) != BUFFER_SIZE) {&lt;br /&gt;			errno = WSAGetLastError();&lt;br /&gt;			if (errno == WSAEWOULDBLOCK ||&lt;br /&gt;				errno == WSAENOBUFS)&lt;br /&gt;				continue;&lt;br /&gt;			&lt;br /&gt;			fatal_error("send() error in client thread");&lt;br /&gt;		}&lt;br /&gt;		total_bytes_sent += bytes_sent;&lt;br /&gt;&lt;br /&gt;		num_to_read = 0;&lt;br /&gt;		if (ioctlsocket(client_sock, FIONREAD, &amp;num_to_read) &lt; 0) &lt;br /&gt;			fatal_error("FIONREAD error in client thread");&lt;br /&gt;		&lt;br /&gt;		if (num_to_read == 0)&lt;br /&gt;			continue;&lt;br /&gt;		&lt;br /&gt;		if ((bytes_received =&lt;br /&gt;		     recv(client_sock, buffer, &lt;br /&gt;			  num_to_read &gt;= BUFFER_SIZE ?&lt;br /&gt;			  BUFFER_SIZE - 1 : num_to_read, 0)) &lt;= 0)&lt;br /&gt;			fatal_error("recv() error in client thread");&lt;br /&gt;		total_bytes_received += bytes_received; 		&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	printf("thread %d total bytes received %d sent %d\n",&lt;br /&gt;	       client_thread_arg-&gt;id, total_bytes_received, total_bytes_sent);&lt;br /&gt;&lt;br /&gt;#if 0&lt;br /&gt;	closesocket(client_sock);&lt;br /&gt;#endif&lt;br /&gt;	free(args);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void *starter_thread(void *args)&lt;br /&gt;{&lt;br /&gt;	HANDLE thread_handles[NUM_THREADS];&lt;br /&gt;	DWORD thread_ids[NUM_THREADS];&lt;br /&gt;	struct thread_args *client_thread_arg;&lt;br /&gt;	int i;&lt;br /&gt;	&lt;br /&gt;	for (i = 0; i &lt; NUM_THREADS; i++) {&lt;br /&gt;		if ((client_thread_arg = &lt;br /&gt;		     (struct thread_args *)&lt;br /&gt;		     malloc(sizeof(struct thread_args))) == 0) &lt;br /&gt;			fatal_error2("malloc client_thread_arg error");&lt;br /&gt;		&lt;br /&gt;		memcpy(client_thread_arg, args, sizeof(struct thread_args));&lt;br /&gt;		client_thread_arg-&gt;id = i;&lt;br /&gt;&lt;br /&gt;		if ((thread_handles[i] =&lt;br /&gt;		     CreateThread(0, 0,&lt;br /&gt;				  (LPTHREAD_START_ROUTINE) client_thread,&lt;br /&gt;				  client_thread_arg, 0,&lt;br /&gt;				  (LPDWORD)&amp;thread_ids[i])) == 0) &lt;br /&gt;			fatal_error2("CreateThread for clients error");&lt;br /&gt;&lt;br /&gt;		printf("created client thread %d\n", i); fflush(stdout);&lt;br /&gt;	}&lt;br /&gt;	free(args);&lt;br /&gt;	args = 0;&lt;br /&gt;&lt;br /&gt;	printf("%d threads created\n", NUM_THREADS); fflush(stdout);&lt;br /&gt;	&lt;br /&gt;	for (i = 0; i &lt; NUM_THREADS; i++) &lt;br /&gt;		WaitForSingleObject(thread_handles[i], INFINITE);&lt;br /&gt;	&lt;br /&gt;	printf("all threads terminated\n"); fflush(stdout);&lt;br /&gt;&lt;br /&gt;	threads_all_done = 1;&lt;br /&gt;	&lt;br /&gt;	ExitThread(0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(void)&lt;br /&gt;{&lt;br /&gt;	int server_sock, client_sock;    &lt;br /&gt;	struct sockaddr_in server_addr, client_addr; &lt;br /&gt;	int client_addr_len;&lt;br /&gt;	unsigned short server_port;   &lt;br /&gt;	char buffer[BUFFER_SIZE];    &lt;br /&gt;	int bytes_received, total_bytes_received; &lt;br /&gt;	int bytes_sent, total_bytes_sent;&lt;br /&gt;	int on = 1;&lt;br /&gt;	unsigned long num_to_read;&lt;br /&gt;	struct timeval timeout;&lt;br /&gt;	struct thread_args *starter_thread_arg;&lt;br /&gt;	WSADATA wsa_data;     &lt;br /&gt;	HANDLE starter_thread_handle;&lt;br /&gt;	DWORD starter_thread_id;&lt;br /&gt;	int client_sockets[NUM_THREADS];&lt;br /&gt;	fd_set socket_fds;&lt;br /&gt;	int size;&lt;br /&gt;	int i;&lt;br /&gt;&lt;br /&gt;	total_bytes_received = total_bytes_sent = 0;&lt;br /&gt;	&lt;br /&gt;	if (WSAStartup(MAKEWORD(2, 0), &amp;wsa_data) != 0) {&lt;br /&gt;		fprintf(stderr, "WSAStartup() error");&lt;br /&gt;		exit(1);&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	total_bytes_received = 0;&lt;br /&gt;	total_bytes_sent = 0;&lt;br /&gt;	&lt;br /&gt;	if ((server_sock = socket(PF_INET, SOCK_STREAM,&lt;br /&gt;				  IPPROTO_TCP)) &lt; 0)&lt;br /&gt;		fatal_error("socket() error");&lt;br /&gt;	&lt;br /&gt;	memset(&amp;client_addr, 0, sizeof(client_addr));     &lt;br /&gt;	memset(&amp;server_addr, 0, sizeof(server_addr));     &lt;br /&gt;	server_addr.sin_family  = AF_INET;       &lt;br /&gt;	server_addr.sin_addr.s_addr = htonl(INADDR_ANY); &lt;br /&gt;	server_addr.sin_port = htons(SERVER_PORT);&lt;br /&gt;	&lt;br /&gt;	if (bind(server_sock, (struct sockaddr *) &amp;server_addr,&lt;br /&gt;		 sizeof(server_addr)) &lt; 0)&lt;br /&gt;		fatal_error ("bind() error ");&lt;br /&gt;	if (listen(server_sock, 5) &lt; 0)&lt;br /&gt;		fatal_error("listen() error");&lt;br /&gt;	&lt;br /&gt;	if ((starter_thread_arg =&lt;br /&gt;	     (struct thread_args *)&lt;br /&gt;	     malloc(sizeof(struct thread_args))) == 0)&lt;br /&gt;		fatal_error("malloc starter_thread_arg error");&lt;br /&gt;&lt;br /&gt;	starter_thread_arg-&gt;server_sock = server_sock;&lt;br /&gt;	server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);&lt;br /&gt;	memcpy(&amp;starter_thread_arg-&gt;server_addr , &amp;server_addr,&lt;br /&gt;	       sizeof(server_addr));&lt;br /&gt;	starter_thread_arg-&gt;id = -1;&lt;br /&gt;	&lt;br /&gt;	if ((starter_thread_handle =&lt;br /&gt;	     CreateThread(0,0,&lt;br /&gt;			  (LPTHREAD_START_ROUTINE)starter_thread,&lt;br /&gt;			  starter_thread_arg, 0,&lt;br /&gt;			  (LPDWORD)&amp;starter_thread_id)) == 0)&lt;br /&gt;		fatal_error("CreateThread for starter thread error");&lt;br /&gt;	&lt;br /&gt;	for (i = 0; i &lt; NUM_THREADS; i++) {&lt;br /&gt;		client_addr_len = sizeof(client_addr);&lt;br /&gt;		if ((client_sock = accept(server_sock,&lt;br /&gt;					  (struct sockaddr *) &amp;client_addr,&lt;br /&gt;					  &amp;client_addr_len)) &lt; 0)&lt;br /&gt;			fatal_error("accept() error");&lt;br /&gt;#if 0&lt;br /&gt;		printf("connection accepted from %s\n",&lt;br /&gt;		       inet_ntoa(client_addr.sin_addr));&lt;br /&gt;#endif&lt;br /&gt;		client_sockets[i] = client_sock;&lt;br /&gt;	}&lt;br /&gt;	printf("%d clients accepted\n", NUM_THREADS);&lt;br /&gt;&lt;br /&gt;	/* send startup message to all clients */&lt;br /&gt;	for (i = 0; i &lt; NUM_THREADS; i++) {&lt;br /&gt;		int startup_msg_len ;&lt;br /&gt;&lt;br /&gt;		client_sock = client_sockets[i];&lt;br /&gt;		memset(buffer, 0, sizeof(buffer));&lt;br /&gt;		strcpy(buffer, "startup");&lt;br /&gt;		startup_msg_len = strlen(buffer);&lt;br /&gt;		if ((bytes_sent =&lt;br /&gt;		     send(client_sock, buffer,&lt;br /&gt;			  startup_msg_len, 0)) != startup_msg_len)&lt;br /&gt;			fatal_error("sending start signal failed");&lt;br /&gt;&lt;br /&gt;		size = SERVER_SEND_SOCK_BUFFER_SIZE;&lt;br /&gt;		if (setsockopt(client_sock, SOL_SOCKET, SO_SNDBUF, &amp;size, sizeof(size)) &lt; 0)&lt;br /&gt;			fatal_error("SO_SNDBUF error  ");&lt;br /&gt;		size = SERVER_RECV_SOCK_BUFFER_SIZE;&lt;br /&gt;		if (setsockopt(client_sock, SOL_SOCKET, SO_RCVBUF, &amp;size, sizeof(size)) &lt; 0)&lt;br /&gt;			fatal_error("SO_RCVBUF error ");&lt;br /&gt;	&lt;br /&gt;		if (ioctlsocket(client_sock, FIONBIO, &amp;on) &lt; 0)&lt;br /&gt;			fatal_error("FIONBIO error");&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	printf("sent startup messages\n"); fflush(stdout);&lt;br /&gt;	for (;;)  {&lt;br /&gt;		int half = BUFFER_SIZE / 2;&lt;br /&gt;&lt;br /&gt;		if (threads_all_done) break;&lt;br /&gt;&lt;br /&gt;		Sleep(100);	/* slow down server artificially */&lt;br /&gt;		&lt;br /&gt;		FD_ZERO(&amp;socket_fds);&lt;br /&gt;		for (i = 0; i &lt; NUM_THREADS; i++)&lt;br /&gt;			FD_SET(client_sockets[i], &amp;socket_fds);&lt;br /&gt;		timeout.tv_sec = 0;&lt;br /&gt;		timeout.tv_usec = 10000;&lt;br /&gt;&lt;br /&gt;		if (select(0, &amp;socket_fds, 0, 0, &amp;timeout) == 0)&lt;br /&gt;			continue;&lt;br /&gt;&lt;br /&gt;		for (i = 0; i &lt; NUM_THREADS; i++) {&lt;br /&gt;			int errno;&lt;br /&gt;			&lt;br /&gt;			if (! FD_ISSET(client_sockets[i], &amp;socket_fds))&lt;br /&gt;				continue;&lt;br /&gt;&lt;br /&gt;			client_sock = client_sockets[i];&lt;br /&gt;&lt;br /&gt;			/* send half as much */&lt;br /&gt;			if ((bytes_sent =&lt;br /&gt;			     send(client_sock, buffer,&lt;br /&gt;				 half, 0)) != half) {&lt;br /&gt;				errno = WSAGetLastError();&lt;br /&gt;				if (errno == WSAEWOULDBLOCK ||&lt;br /&gt;				    errno == WSAENOBUFS)&lt;br /&gt;					continue;&lt;br /&gt;				fatal_error("send() error");&lt;br /&gt;			}&lt;br /&gt;			total_bytes_sent += bytes_sent;&lt;br /&gt;			&lt;br /&gt;			num_to_read = 0;&lt;br /&gt;			if (ioctlsocket(client_sock, FIONREAD, &amp;num_to_read) &lt; 0) &lt;br /&gt;				fatal_error("FIONREAD error");&lt;br /&gt;			&lt;br /&gt;			if (num_to_read == 0)&lt;br /&gt;				continue;&lt;br /&gt;			&lt;br /&gt;			/* read half as much */&lt;br /&gt;			num_to_read = num_to_read &gt;= half ? half - 1 : num_to_read;&lt;br /&gt;			if ((bytes_received =&lt;br /&gt;			     recv(client_sock, buffer, num_to_read, 0)) &lt;= 0)&lt;br /&gt;				fatal_error("recv() error ");&lt;br /&gt;			total_bytes_received += bytes_received;&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	closesocket(server_sock);&lt;br /&gt;	closesocket(client_sock);&lt;br /&gt;	WSACleanup();&lt;br /&gt;	WaitForSingleObject(starter_thread_handle, INFINITE);&lt;br /&gt;&lt;br /&gt;	printf("all threads finished. total bytes received %d sent %d\n",&lt;br /&gt;	       total_bytes_received, total_bytes_sent);&lt;br /&gt;	&lt;br /&gt;	exit(0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Sat, 26 Aug 2006 07:13:25 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/2471</guid>
      <author>frontera000 (bob bae)</author>
    </item>
  </channel>
</rss>
