Пишем кроссплатформенный сервер

Пишем кроссплатформенный сервер
В рамках изучения сокетов решил написать простой plaintext-сервер, но не совсем простой, а кроссплатформенный.
Языком разработки был выбран C++. Под Windows — MSVC, под Linux — G++.
Первая (и самая главная) проблема состоит в разности заголовочных файлов у Visual C++ и GNU C++. В Visual C++ все необходимые функции и типы сокетов описаны в файле winsock.h, а в GNU C++ в нескольких: sys/types.h, sys/socket.h и netinet/in.h. Более того, этих файлов в MSVC нет.
Второй проблемой является отсутствие в GNU C++ типа SOCKET и некоторых важных констант.
Эти проблемы можно решить установкой директивы компилятора, которая будет проверять тип операционной системы и в зависимости от операционной системы подключать разные заголовочные файлы:
#include <stdio.h>
#ifdef WIN32
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
#define SOCKET int
#endif

Третья проблема заключается в необходимости инициализации технологии WinSock в Windows, без чего доступа к сокетам в Windows получить не удастся. Поэтому блок, отвечающий за это также нужно заключить в директиву проверки операционной системы.
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,2), &wsadata);
#endif

В остальном работа с сокетами в Windows и Linux ничем не отличается, за исключением отсутствия во втором функции closesocket (), вместо которой придется использовать shutdown ().
Код моего plaintext-сервера представлени ниже:
SOCKET s_server, s_client; // сокеты клиента и севера
sockaddr_in ssin; // адрес сокета
char * buffer = new char[1024]; // буфер данных
int len; // длина данных

// создаем сокет
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (s_server == SOCKET_ERROR)
return 0;

// формируем адрес сокета
ssin.sin_family = AF_INET;
ssin.sin_addr.s_addr = INADDR_ANY;
ssin.sin_port = htons(SRV_PORT);

// Привязываем сокет к адресу
if (bind(s_server, (sockaddr *)&ssin, sizeof(ssin)) == SOCKET_ERROR)
return 0;

// начинаем прослушку
listen(s_server, 5);
while(1)
{
// принимаем подключение
s_client = accept(s_server, NULL, NULL);
if (s_client == INVALID_SOCKET)
return 0;

// принимаем запрос от клиента
len = recv(s_client, buffer, MAXDATA, 0);
if (len == SOCKET_ERROR)
return 0;
buffer[len] = 0;

printf("%s\n",buffer);

// отправляем ответ
sprintf(buffer, "Got %d bytes of data.", len);
len = send(s_client, buffer, strlen(buffer), 0);
if (len == SOCKET_ERROR)
return 0;
// закрываем сокет
//closesocket(s_client);
shutdown(s_client, 1);
}

//closesocket(s_server);
shutdown(s_server, 1);

Исходный код проекта для Microsoft Visual Studio можно скачать тут.

Поблагодарить автора

Оставить комментарий

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>