Tag Archives: Windows

Downloading a Web page in C using WinINet


/* Link with Wininet.lib */
#include <windows.h>
#include <wininet.h>
#include <stdio.h>

int main(void)
{
	HINTERNET hInternet, hFile;
	char buf[1024];
	DWORD bytes_read;
	int finished = 0;
	hInternet = InternetOpen("", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
	if (hInternet == NULL) {
		printf("InternetOpen failed\n");
		return 1;
	}
	hFile = InternetOpenUrl(hInternet, "http://www.martinbroadhurst.com", NULL, 0L, 0, 0);
	if (hFile == NULL) {
		printf("InternetOpenUrl failed\n");
		return 1;
	}
	while (!finished) {
		if (InternetReadFile(hFile, buf, sizeof(buf), &bytes_read)) {
			if (bytes_read > 0) {
				printf("%.*s", bytes_read, buf);
			}
			else {
				finished = 1;
			}
		}
		else {
			printf("InternetReadFile failed\n");
			finished = 1;
		}
	}
	InternetCloseHandle(hInternet);
	InternetCloseHandle(hFile);
			
	return 0;
}

Reference: InternetOpenUrl function

Downloading a Web page in C using a Windows socket

/* Link with Ws2_32.lib */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>


int main(void)
{
	WSADATA wsaData;
	WORD wVersion;
	SOCKET sock;
	char host[] = "www.martinbroadhurst.com";
	char port[] = "80";
	struct addrinfo hints, *res;
	char message[] = "GET / HTTP/1.1\nHost: www.martinbroadhurst.com\n\n";
	char buf[1024];
	int bytes_read;
	int status;

	wVersion = MAKEWORD(1, 1);
	if (WSAStartup(wVersion, &wsaData) != 0) {
		printf("Couldn't initialise WinSock\n");
		return 1;
	}

	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	status = getaddrinfo(host, port, &hints, &res);
	if (status != 0) {
		perror("getaddrinfo");
        WSACleanup();
		return 1;
	}
	sock = socket(AF_INET, SOCK_STREAM, 0);

	status = connect(sock, res->ai_addr, res->ai_addrlen);
	if (status == SOCKET_ERROR) {
		perror("connect");
        WSACleanup();
		return 1;
	}

	send(sock, message, sizeof(message), 0);

    do {
		bytes_read = recv(sock, buf, sizeof(buf), 0);
		if (bytes_read == SOCKET_ERROR) {
			perror("recv");
		}
		else {
			printf("%.*s", bytes_read, buf);
		}
	} while (bytes_read > 0);

	closesocket(sock);
	WSACleanup();
    return 0;
}

Reference: Using Winsock

Sleep for milliseconds in C++

Method 1: Use usleep (POSIX)

#include <unistd.h>

int main()
{
    usleep(500);
}

Method 2: Use Sleep (Windows)

#include <Windows.h>

int main()
{
    Sleep(500);
}

Method 3: Use Boost.Thread

#include <boost/thread/thread.hpp>
int main()
{
    boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}

Method 4: Use std::this_thread::sleep_for (C++11)

#include <chrono>
#include <thread>

int main()
{
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

List the Files in a Directory in C++

Imagine that we want to populate a vector with the names of the files in a directory with a read_directory() function like this:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

typedef std::vector<std::string> stringvec;

int main()
{
    stringvec v;
    read_directory(".", v);
    std::copy(v.begin(), v.end(),
         std::ostream_iterator<std::string>(std::cout, "\n"));
}

Method 1: Use boost_filesystem

#include <boost/filesystem.hpp>

struct path_leaf_string
{
    std::string operator()(const boost::filesystem::directory_entry& entry) const
    {
        return entry.path().leaf().string();
    }
};

void read_directory(const std::string& name, stringvec& v)
{
    boost::filesystem::path p(name);
    boost::filesystem::directory_iterator start(p);
    boost::filesystem::directory_iterator end;
    std::transform(start, end, std::back_inserter(v), path_leaf_string());
}

Reference: Boost Filesystem Library Version 3

Method 2: Use opendir()/readdir()/closedir() (POSIX)

#include <sys/types.h>
#include <dirent.h>

void read_directory(const std::string& name, stringvec& v)
{
    DIR* dirp = opendir(name.c_str());
    struct dirent * dp;
    while ((dp = readdir(dirp)) != NULL) {
        v.push_back(dp->d_name);
    }
    closedir(dirp);
}

Reference: readdir – The Open Group

Method 3: Use FindFirstFile()/FindNextFile()/FindClose() (Windows)

#include <windows.h>

void read_directory(const std::string& name, stringvec& v)
{
    std::string pattern(name);
    pattern.append("\\*");
    WIN32_FIND_DATA data;
    HANDLE hFind;
    if ((hFind = FindFirstFile(pattern.c_str(), &data)) != INVALID_HANDLE_VALUE) {
        do {
            v.push_back(data.cFileName);
        } while (FindNextFile(hFind, &data) != 0);
        FindClose(hFind);
    }
}

Reference: FindFirstFile function

TCP Proxy for Windows

This is the Windows version of TCP Proxy.

/* 
 *  A simple TCP proxy for Windows
 *  by Martin Broadhurst (www.martinbroadhurst.com)
 *  Link with Ws2_32.lib
 *  Usage: tcpproxy local_host local_port remote_host remote_port
 */

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#define _WINSOCK_DEPRECATED_NO_WARNINGS /* inet_ntoa */

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define BACKLOG  10      /* Passed to listen() */
#define BUF_SIZE 4096    /* Buffer for  transfers */

unsigned int transfer(SOCKET from, SOCKET to)
{
	char buf[BUF_SIZE];
	unsigned int disconnected = 0;
	size_t bytes_read, bytes_written;
	bytes_read = recv(from, buf, BUF_SIZE, 0);
	if (bytes_read == 0) {
		disconnected = 1;
	}
	else {
		bytes_written = send(to, buf, bytes_read, 0);
		if (bytes_written == -1) {
			disconnected = 1;
		}
	}
	return disconnected;
}

void handle(SOCKET client, const char *remote_host, const char *remote_port)
{
	struct addrinfo hints, *res;
	SOCKET server = -1;
	unsigned int disconnected = 0;
	fd_set set;
	unsigned int max_sock;

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(remote_host, remote_port, &hints, &res) != 0) {
		perror("getaddrinfo");
		closesocket(client);
		return;
	}

	/* Create the socket */
    server = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (server == INVALID_SOCKET) {
		perror("socket");
		closesocket(client);
		return;
	}

	/* Connect to the host */
	if (connect(server, res->ai_addr, res->ai_addrlen) == -1) {
		perror("connect");
		closesocket(client);
		return;
    }

	if (client > server) {
		max_sock = client;
	}
	else {
		max_sock = server;
	}

	/* Main transfer loop */
	while (!disconnected) {
		FD_ZERO(&set);
		FD_SET(client, &set);
		FD_SET(server, &set);
		if (select(max_sock + 1, &set, NULL, NULL, NULL) == SOCKET_ERROR) {
			perror("select");
			break;
		}
		if (FD_ISSET(client, &set)) {
			disconnected = transfer(client, server);
		}
		if (FD_ISSET(server, &set)) {
			disconnected = transfer(server, client);
		}
	}
	if (server != -1) {
		closesocket(server);
	}
	closesocket(client);
}

int main(int argc, char **argv)
{
	WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int iResult;
    SOCKET sock;
	struct addrinfo hints, *res;
	int reuseaddr = 1; /* True */
	const char *local_host, *local_port, *remote_host, *remote_port;

	/* Initialise Winsock */
	if (iResult = (WSAStartup(wVersion, &wsaData)) != 0) {
		fprintf(stderr, "WSAStartup failed: %d\n", iResult);
		return 1;
	}

	/* Get the local and remote hosts and ports from the command line */
	if (argc < 5) {
		fprintf(stderr, "Usage: tcpproxy local_host local_port remote_host remote_port\n");
		return 1;
	}
	local_host = argv[1];
	local_port = argv[2];
	remote_host = argv[3];
	remote_port = argv[4];

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(local_host, local_port, &hints, &res) != 0) {
		perror("getaddrinfo");
		WSACleanup();
		return 1;
	}

	/* Create the socket */
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock == INVALID_SOCKET) {
		perror("socket");
		WSACleanup();
		return 1;
	}

	/* Enable the socket to reuse the address */
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, 
		sizeof(int)) == SOCKET_ERROR) {
		perror("setsockopt");
		WSACleanup();
		return 1;
	}

	/* Bind to the address */
    if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
        perror("bind");
		WSACleanup();
        return 1;
    }

	/* Listen */
    if (listen(sock, BACKLOG) == SOCKET_ERROR) {
        perror("listen");
		WSACleanup();
        return 1;
    }

	freeaddrinfo(res);
 
	/* Main loop */
	while (1) {
		size_t size = sizeof(struct sockaddr_in);
		struct sockaddr_in their_addr;
		int newsock = accept(sock, (struct sockaddr*)&their_addr, &size);

		if (newsock == INVALID_SOCKET) {
			perror("accept");
		}
		else {
			printf("Got a connection from %s on port %d\n", 
					inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
			handle(newsock, remote_host, remote_port);
		}
	}

    closesocket(sock);
	WSACleanup();

    return 0;
}

Select server for windows

This is the Windows version of the Select Server.

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define PORT    "32001" /* Port to listen on */
#define BACKLOG 10		/* Passed to listen() */

void handle(SOCKET newsock, fd_set *set)
{
    /* send(), recv(), closesocket() */
	/* Call FD_CLR(newsock, set) on disconnection */
}

int main(void)
{
    WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int iResult;
	SOCKET sock;
	fd_set socks;
	fd_set readsocks;
	SOCKET maxsock;
	int reuseaddr = 1; /* True */
	struct addrinfo hints, *res;

	/* Initialise Winsock */
	if (iResult = (WSAStartup(wVersion, &wsaData)) != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(NULL, PORT, &hints, &res) != 0) {
		perror("getaddrinfo");
		WSACleanup();
		return 1;
	}

	/* Create the socket */
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock == -1) {
		perror("socket");
		WSACleanup();
		return 1;
	}

	/* Enable the socket to reuse the address */
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, 
				sizeof(int)) == SOCKET_ERROR) {
		perror("setsockopt");
		WSACleanup();
		return 1;
	}

	/* Bind to the address */
    if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
        perror("bind");
		WSACleanup();
        return 1;
    }

	/* Listen */
    if (listen(sock, BACKLOG) == SOCKET_ERROR) {
        perror("listen");
		WSACleanup();
        return 1;
    }

	/* Set up the fd_set */
	FD_ZERO(&socks);
	FD_SET(sock, &socks);
	maxsock = sock;

	/* Main loop */
	while (1) {
		SOCKET s;
		readsocks = socks;
		if (select(maxsock + 1, &readsocks, NULL, NULL, NULL) == SOCKET_ERROR) {
			perror("select");
			WSACleanup();
			return 1;
		}
		for (s = 0; s <= maxsock; s++) {
			if (FD_ISSET(s, &readsocks)) {
				printf("Socket %d was ready\n", s);
				if (s == sock) {
					/* New connection */
					SOCKET newsock;
					struct sockaddr_in their_addr;
					size_t size = sizeof(struct sockaddr_in);

					newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
					if (newsock == INVALID_SOCKET) {
						perror("accept");
					}
					else {
						printf("Got a connection from %s on port %d\n", 
								inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
						FD_SET(newsock, &socks);
						if (newsock > maxsock) {
							maxsock = newsock;
						}
					}
				}
				else {
					/* Handle read or disconnection */
					handle(s, &socks);
				}
			}
		}
	}

	/* Clean up */
    closesocket(sock);
	WSACleanup();

    return 0;
}

Threaded server for Windows

This is the Windows version of the Threaded Server.

/* 
 *  Link with Ws2_32.lib
 */

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h> /* _beginthread() */

#define PORT    "32001" /* Port to listen on */
#define BACKLOG 10		/* Passed to listen() */

void handle(void *pParam)
{
	/* send(), recv(), closesocket() */

    free(pParam);
}

int main(void)
{
	WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int iResult;
	SOCKET sock;
	struct addrinfo hints, *res;
	int reuseaddr = 1; /* True */

	/* Initialise Winsock */
	if ((iResult = WSAStartup(wVersion, &wsaData)) != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(NULL, PORT, &hints, &res) != 0) {
		perror("getaddrinfo");
		return 1;
	}

	/* Create the socket */
	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock == INVALID_SOCKET) {
		perror("socket");
		WSACleanup();
		return 1;
	}

	/* Enable the socket to reuse the address */
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseaddr, 
				sizeof(int)) == SOCKET_ERROR) {
		perror("setsockopt");
		WSACleanup();
		return 1;
	}

	/* Bind to the address */
	if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
		perror("bind");
		WSACleanup();
		return 1;
	}

	freeaddrinfo(res);

	/* Listen */
	if (listen(sock, BACKLOG) == SOCKET_ERROR) {
		perror("listen");
		WSACleanup();
		return 1;
	}

	/* Main loop */
	while(1) {
		size_t size = sizeof(struct sockaddr);
		struct sockaddr_in their_addr;
		SOCKET newsock;

		ZeroMemory(&their_addr, sizeof (struct sockaddr));
		newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
		if (newsock == INVALID_SOCKET) {
			perror("accept\n");
		}
		else {
			/* Use the new socket */
			uintptr_t thread;
			printf("Got a connection from %s on port %d\n", 
				inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port));
			printf("New socket is %d\n", newsock);
            /* Make a safe copy of newsock */
            int *safesock = malloc(sizeof(int));
            if (safesock) {
                *safesock = newsock;
                thread = _beginthread(handle, 0, safesock);
                if (thread == -1) {
                    fprintf(stderr, "Couldn't create thread: %d\n", GetLastError());
                    closesocket(newsock);
                }
            }
            else {
                perror("malloc");
            }
		}
	}

	/* Clean up */
	closesocket(sock);
	WSACleanup();

	return 0;
}

Simple server for Windows

This is the Windows version of the Simple Server.

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define PORT    "32001" /* Port to listen on */
#define BACKLOG 10		/* Passed to listen() */

void handle(SOCKET newsock)
{
    /* send(), recv(), closesocket() */
}

int main(void)
{
	WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int iResult;
	SOCKET sock;
	struct addrinfo hints, *res;
	int reuseaddr = 1; /* True */
	
	/* Initialise Winsock */
	if ((iResult = WSAStartup(wVersion, &wsaData)) != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(NULL, PORT, &hints, &res) != 0) {
		perror("getaddrinfo");
		return 1;
	}

	/* Create the socket */
	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock == INVALID_SOCKET) {
		perror("socket");
		WSACleanup();
		return 1;
	}

	/* Enable the socket to reuse the address */
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseaddr, sizeof(int)) == SOCKET_ERROR) {
		perror("setsockopt");
		WSACleanup();
		return 1;
	}

	/* Bind to the address */
	if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
		perror("bind");
		WSACleanup();
		return 1;
	}

	/* Listen */
	if (listen(sock, BACKLOG) == SOCKET_ERROR) {
		perror("listen");
		WSACleanup();
		return 1;
	}

	freeaddrinfo(res);

	/* Main loop */
	while(1) {
		size_t size = sizeof(struct sockaddr);
		struct sockaddr_in their_addr;
		SOCKET newsock;

		ZeroMemory(&their_addr, sizeof (struct sockaddr));
		newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
		if (newsock == INVALID_SOCKET) {
			perror("accept\n");
		}
		else {
			printf("Got a connection from %s on port %d\n", 
				inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port));

			handle(newsock);
		}
	}

	/* Clean up */
	closesocket(sock);
	WSACleanup();

	return 0;
}