I have planned to implement a networking library for C++ which is specific to windows since I can't find a library for my needs. Here is an implementation of TCP server using this library.
First of all we need sockets so socket.h
// SWAMI KARUPPASWAMI THUNNAI
#pragma once
#ifndef SOCKET_H
#define SOCKET_H
#include<windows.h>
#include<winsock.h>
#include<string>
#include"exceptions.h"
#pragma comment(lib, "ws2_32.lib")
/**
DESCRIPTION:
In networking there are two primary types of socket
1. TCP
2. UDP
This class will give you the above specified socket of your choice
*/
class Socket
{
private:
WSADATA winsock;
SOCKET sock;
protected:
const enum {
TCP = 0,
UDP = 1
};
public:
Socket();
// Will return the socket of specified type
// type = 0 for TCP
// type = 1 for UDP
// Throws: socket_error
SOCKET get_socket(int type);
/**
Description:
-------------
This method is used to send message on the specified socket
Throws:
--------
socket_error
*/
void send_message(SOCKET s, std::string message);
/**
Description:
-------------
Will receive the message from the client with
the specified buffer size
*/
char* receive(SOCKET client_socket, int buffer_size);
};
#endif // SOCKET_H
and socket.cpp
// SWAMI KARUPPASWAMI THUNNAI
#include "socket.h"
Socket::Socket()
{
// Initialize the winsock
if ((WSAStartup(MAKEWORD(2, 2), &winsock) != 0))throw winsock_initialize_error();
}
SOCKET Socket::get_socket(int type)
{
switch (type)
{
case TCP:
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) throw socket_error_invalid();
return sock;
case UDP:
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) throw socket_error_invalid();
return sock;
default:
break;
}
return SOCKET();
}
void Socket::send_message(SOCKET s, std::string message)
{
// Send the message back
int result = send(s, message.c_str(), message.size(), 0);
if (result == SOCKET_ERROR) throw socket_error();
}
char * Socket::receive(SOCKET client_socket, int buffer_size)
{
char* buffer = new char[buffer_size];
recv(client_socket, buffer, buffer_size, 0);
return buffer;
}
and server_socket.h
#pragma once
#include"socket.h"
#include<string>
/**
This namespace will contain classes which provides specifc sockets
for various protocols like TCP, UDP etc.,
*/
namespace server_socket
{
/**
RFC:
----
The Transmission Control Protocol (TCP) is intended for use as a highly
reliable host-to-host protocol between hosts in packet-switched computer
communication networks, and in interconnected systems of such networks.
*/
class tcp :public Socket
{
private:
SOCKET socket;
sockaddr_in server;
public:
/**
Description:
------------
A constructor to bind the specific ip address on a particular port number
Throws:
--------
bind_error if the port is already in use
*/
tcp(std::string ip_address, int port_no);
/**
Description:
------------
Will listen for a specified backlog
Throws:
-------
listen_error
*/
void tcp_listen(int backlog);
/**
Description:
-------------
Will accept connections from the client
*/
void accept_client(SOCKET& client, sockaddr_in& from);
/**
Description:
-------------
Will close the particular socket
*/
void close(SOCKET& socket);
/**
Description:
-------------
Will close the TCP connection itself.
*/
void close();
};
}
server_socket_tcp.cpp
#include "server_socket.h"
#include<iostream>
server_socket::tcp::tcp(std::string ip_address, int port_no)
{
// Initialize the socket to tcp
socket = get_socket(TCP);
// Initialize the server's ip family to IP version 4
server.sin_family = AF_INET;
// Server's ip address
server.sin_addr.S_un.S_addr = inet_addr(ip_address.c_str());
// Server's port no
server.sin_port = htons(port_no);
// Now bind the server on the specific port
if (bind(socket, (struct sockaddr*)&server, sizeof(server)) < 0) throw bind_error();
}
void server_socket::tcp::tcp_listen(int backlog)
{
if (listen(socket, backlog) != 0) throw listen_error();
}
void server_socket::tcp::accept_client(SOCKET& client, sockaddr_in& from)
{
int size = sizeof(from);
client = accept(socket, (sockaddr*)&from, &size);
}
void server_socket::tcp::close()
{
closesocket(socket);
}
void server_socket::tcp::close(SOCKET& socket)
{
closesocket(socket);
}
Finally TCP server
#include<iostream>
#include"server_socket.h"
int main()
{
try {
server_socket::tcp server("127.0.0.1", 90);
server.tcp_listen(10);
std::cout << "The server is listening\n";
sockaddr_in from;
SOCKET client;
while (true) //we are looping endlessly
{
server.accept_client(client, from);
std::cout << "Accepted connection\n";
std::cout << server.receive(client, 4096);
std::cout << "Received\n";
server.send_message(client, "<h1>Hello World</h1>");
}
server.close(); // I know this wont get called :) but in real world applications
// you have to close the tcp connection like this
}
catch (std::exception &e)
{
std::cout << "exception: ";
std::cout << e.what();
}
int a;
std::cin >> a;
}