Задача – реализовать TCP эхо-сервер — КиберПедия 

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Задача – реализовать TCP эхо-сервер

2020-11-19 114
Задача – реализовать TCP эхо-сервер 0.00 из 5.00 0 оценок
Заказать работу

Пример простого TCP -эхо-сервера

# include < stdio. h >
# include < winsock 2. h > // Wincosk 2. h должен быть раньше windows!
# include < windows. h >

# define MY _ PORT 666 // Порт, который слушает сервер 666

// макрос для печати количества активных пользователей
# define PRINTNUSERS if (nclients) printf ("% d user on - line \ n ", nclients); \
else printf (" No User on line \ n ");

// прототип функции, обслуживающий подключившихся пользователей
DWORD WINAPI SexToClient (LPVOID client _ socket);

// глобальная переменная - количество активных пользователей
int nclients = 0;

int main (int argc, char * argv [])
{
char buff [1024]; // Буфер для различных нужд

printf (" TCP SERVER DEMO \ n ");
// Шаг 1 - Инициализация Библиотеки Сокетов
// т.к. возвращенная функцией информация не используется
// ей передается указатель на рабочий буфер, преобразуемый к указателю
// на структуру WSADATA.
// Такой прием позволяет сэкономить одну переменную, однако, буфер
// должен быть не менее полкилобайта размером (структура WSADATA // занимает 400 байт)
if (WSAStartup (0 x 0202, (WSADATA *)& buff [0]))
{
// Ошибка!
printf("Error WSAStartup %d\n", WSAGetLastError());
return -1;
}

// Шаг 2 - создание сокета
SOCKET mysocket;
// AF_INET - сокет Интернета
// SOCK_STREAM - потоковый сокет (с установкой соединения)
// 0 - по умолчанию выбирается TCP протокол
if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
// Ошибка!
printf("Error socket %d\n", WSAGetLastError());
WSACleanup(); // Деиницилизация библиотеки Winsock
return -1;
}

// Шаг 3 - связывание сокета с локальным адресом
sockaddr_in local_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(MY_PORT); // не забываем о сетевом порядке!!!
local_addr.sin_addr.s_addr = 0; // сервер принимает подключения
// на все свои IP-адреса

// вызываем bind для связывания
if (bind(mysocket, (sockaddr *)&local_addr, sizeof(local_addr)))
{
// Ошибка
printf("Error bind %d\n", WSAGetLastError());
closesocket(mysocket); // закрываем сокет!
WSACleanup();
return -1;
}

// Шаг 4 - ожидание подключений
// размер очереди - 0x100
if (listen(mysocket, 0x100))
{
// Ошибка
printf("Error listen %d\n", WSAGetLastError());
closesocket(mysocket);
WSACleanup();
return -1;
}

printf("Ожидание подключений...\n");

// Шаг 5 - извлекаем сообщение из очереди
SOCKET client_socket; // сокет для клиента
sockaddr_in client_addr; // адрес клиента (заполняется системой)

// функции accept необходимо передать размер структуры
int client_addr_size = sizeof(client_addr);

// цикл извлечения запросов на подключение из очереди
while ((client_socket = accept(mysocket, (sockaddr *)&client_addr, \
&client_addr_size)))
{
nclients++; // увеличиваем счетчик подключившихся клиентов

// пытаемся получить имя хоста
HOSTENT *hst;
hst = gethostbyaddr((char *)&client_addr. sin_addr.s_addr, 4, AF_INET);

// вывод сведений о клиенте
printf("+%s [%s] new connect!\n",
(hst)? hst->h_name: "", inet_ntoa(client_addr.sin_addr));
PRINTNUSERS

// Вызов нового потока для обслужвания клиента
// Да, для этого рекомендуется использовать _beginthreadex
// но, поскольку никаких вызовов функций стандартной Си библиотеки
// поток не делает, можно обойтись и CreateThread
DWORD thID;
CreateThread(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
}
return 0;
}

// Эта функция создается в отдельном потоке
// и обсуживает очередного подключившегося клиента независимо от остальных
DWORD WINAPI SexToClient(LPVOID client_socket)
{
SOCKET my_sock;
my_sock = ((SOCKET *)client_socket)[0];
char buff[20 * 1024];
#define sHELLO "Hello, Sailor\r\n"

// отправляем клиенту приветствие
send(my_sock, sHELLO, sizeof(sHELLO), 0);

// цикл эхо-сервера: прием строки от клиента и возвращение ее клиенту
int bytes_recv;
while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) &&
bytes_recv!= SOCKET_ERROR)
send(my_sock, &buff[0], bytes_recv, 0);

// если мы здесь, то произошел выход из цикла по причине
// возращения функцией recv ошибки - соединение с клиентом разорвано
nclients--; // уменьшаем счетчик активных клиентов
printf("-disconnect\n"); PRINTNUSERS

// закрываем сокет
closesocket(my_sock);
return 0;
}

Пример реализации TCP-клиента

// Пример простого TCP-клиента
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>

#define PORT 666
#define SERVERADDR "127.0.0.1"

int main(int argc, char* argv[])
{
char buff[1024];
printf("TCP DEMO CLIENT\n");

// Шаг 1 - инициализация библиотеки Winsock
if (WSAStartup(0x202, (WSADATA *)&buff[0]))
{
printf("WSAStart error %d\n", WSAGetLastError());
return -1;
}

// Шаг 2 - создание сокета
SOCKET my_sock;
my_sock = socket(AF_INET, SOCK_STREAM, 0);
if (my_sock < 0)
{
printf("Socket() error %d\n", WSAGetLastError());
return -1;
}

// Шаг 3 - установка соединения
// заполнение структуры sockaddr_in - указание адреса и порта сервера
sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PORT);
HOSTENT *hst;

// преобразование IP адреса из символьного в сетевой формат
if (inet_addr(SERVERADDR)!= INADDR_NONE)
dest_addr.sin_addr.s_addr = inet_addr(SERVERADDR);
else
{
// попытка получить IP адрес по доменному имени сервера
if (hst = gethostbyname(SERVERADDR))
// hst->h_addr_list содержит не массив адресов,
// а массив указателей на адреса
((unsigned long *)&dest_addr.sin_addr)[0] =
((unsigned long **)hst->h_addr_list)[0][0];
else
{
printf("Invalid address %s\n", SERVERADDR);
closesocket(my_sock);
WSACleanup();
return -1;
}
}

// адрес сервера получен - пытаемся установить соединение
if (connect(my_sock, (sockaddr *)&dest_addr, sizeof(dest_addr)))
{
printf("Connect error %d\n", WSAGetLastError());
return -1;
}

printf("Соединение с %s успешно установлено\n \
Type quit for quit\n\n", SERVERADDR);

// Шаг 4 - чтение и передача сообщений
int nsize;
while ((nsize = recv(my_sock, &buff[0], sizeof(buff) - 1, 0))!= SOCKET_ERROR)
{
// ставим завершающий ноль в конце строки
buff[nsize] = 0;

// выводим на экран
printf("S=>C:%s", buff);

// читаем пользовательский ввод с клавиатуры
printf("S<=C:"); fgets(&buff[0], sizeof(buff) - 1, stdin);

// проверка на "quit"
if (!strcmp(&buff[0], "quit\n"))
{
// Корректный выход
printf("Exit...");
closesocket(my_sock);
WSACleanup();
return 0;
}

// передаем строку клиента серверу
send(my_sock, &buff[0], strlen(&buff[0]), 0);
}
printf("Recv error %d\n", WSAGetLastError());
closesocket(my_sock);
WSACleanup();
return -1;
}

Варианты заданий

Доработать программу задания темы №1.

Клиент должен сформировать пакет данных для расчётов на сервере и передать их по каналу связи. Формат сообщений разработать самостоятельно.

 


Поделиться с друзьями:

Типы оградительных сооружений в морском порту: По расположению оградительных сооружений в плане различают волноломы, обе оконечности...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.011 с.