ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2019
Просмотров: 101
Скачиваний: 1
ЛАБОРАТОРНАЯ РАБОТА №2
ПРОГРАММИРОВАНИЕ СОКЕТОВ. ПРОТОКОЛ UDP
Студента ИТ 14-1 Красовского Абхая
Цель работы: изучить возможности протокола UDP для создания приложений клиент-сервер в синхронном режиме..
Ход работы:
Сервер:
#pragma comment(lib, "Ws2_32.lib") // подключение библиотеки Winsock2
#include <iostream>
#include <winsock2.h>
#define PORT 777 // порт сервера
using namespace std;
void main()
{
system("color 1A");
char buff[1024];
cout << "UDP Server\n";
// Шаг 1 - подключение библиотеки
if (WSAStartup(0x202, // номер версии библиотеки (Winsock)
(WSADATA *)&buff[0]))
cout << "WSAStartup error: " << WSAGetLastError() << endl;
// Шаг 2 - создание сокета
SOCKET my_sock;
my_sock = socket(AF_INET, // семейство используемых протоколов
SOCK_DGRAM, // тип создаваемого потока
0); // транспортный протокол(0 - значение по умолчанию, TDP для потоковых сокетов, UDP для дейтаграммных)
if (my_sock == INVALID_SOCKET)
{
cout << "Socket() error: " << WSAGetLastError() << endl;
WSACleanup();
}
// Шаг 3 - связывание сокета с локальным адресом
sockaddr_in local_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = INADDR_ANY; // коснтанта(0), указывается для связки сервера с несколькими IP-адресами
local_addr.sin_port = htons(PORT);
// функция связывания сокета с локальный адресом
if (bind(my_sock, (sockaddr *)&local_addr, sizeof(local_addr)))
{
cout << "bind error: " << WSAGetLastError() << endl;
closesocket(my_sock);
WSACleanup();
}
// Шаг 4 - обработка пакетов, присланных клиентами
while (true)
{
sockaddr_in client_addr;
int client_addr_size = sizeof(client_addr);
// recvfrom - функция для считывания входящих сообщений
int bsize = recvfrom(my_sock, // сокет через который будем считывать сообщения
&buff[0], // ссылка на первый символ буфера, в который копируется сообщение
sizeof(buff) - 1, // размер буфера
0, // флаги (0 - по умолчанию)
(sockaddr *)&client_addr, // адрес, с которого будем читать сообщения
&client_addr_size); // размер сообщения, которое считываем
if (bsize == SOCKET_ERROR)
cout << "recvfrom() error: " << WSAGetLastError() << endl;
// определяем IP-адрес клиента и прочие атрибуты
HOSTENT *hst;
hst = gethostbyaddr((char *)&client_addr.sin_addr,
4, // длинна адреса в байтах
AF_INET); // тип адреса
printf("+%s [%s:%d] new DATAGRAM!\n", (hst) ? hst->h_name : "Unknown host",
inet_ntoa(client_addr.sin_addr),
/* Функция inet_ntoa() преобразует IP-адрес client_addr.sin_addr,
заданный в сетевом порядке расположения байтов,
в стандартный строчный вид, из номеров и точек..*/
ntohs(client_addr.sin_port));
/* Функция ntohs() преобразует сетевой порядок расположения
байтов положительного короткого целого netshort в узловой
порядок расположения байтов.*/
// добавление завершающего нуля
buff[bsize] = 0;
// вывод на экран
cout << "Client to Server:\n" << &buff[0] << endl;
// посылка дейтаграммы клиенту
sendto(my_sock, &buff[0], bsize, 0, // флаги (0 - по умолчанию)
(sockaddr *)&client_addr, sizeof(client_addr));
}
}
Клиент:
#pragma comment(lib, "Ws2_32.lib")
#include <iostream>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#define PORT 777
#define SERVERADDR "127.0.0.1"
using namespace std;
void freeWsaAndSocket(SOCKET socket)
{
closesocket(socket);
WSACleanup();
}
void main()
{
system("color 1A");
char buff[1024];
cout << "UDP-Client\nType quit to quit\n";
// Шаг 1 - инициализация библиотеки Winsock
if (WSAStartup(0x202, (WSADATA *)&buff[0]))
cout << "WSAStartup error: %d\n" << WSAGetLastError() << endl;
// Шаг 2 - открытие сокета
SOCKET my_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (my_sock == INVALID_SOCKET)
{
cout << "socket() error: %d\n" << WSAGetLastError() << endl;
WSACleanup();
}
// Шаг 3 - обмен сообщений с сервером
HOSTENT *hst;
sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PORT);
// определение IP_адреса узла
if (inet_addr(SERVERADDR)) /* Функция inet_addr() преобразует обычный вид IP-адреса
(из номеров и точек) в двоичный код в сетевом порядке
расположения байтов. Если входящий адрес неверен, то возвращается -1. */
dest_addr.sin_addr.s_addr = inet_addr(SERVERADDR);
else
if (hst = gethostbyname(SERVERADDR))
dest_addr.sin_addr.s_addr = ((unsigned long **)hst->h_addr_list)[0][0];
else
{
cout << "Unknown host: %d\n" << WSAGetLastError() << endl;
freeWsaAndSocket(my_sock);
}
while (true)
{
// чтение сообщения с клавиатуры
cout << "Server <= Client:";
fgets(&buff[0], sizeof(buff) - 1, stdin);
if (!strcmp(&buff[0], "quit\n")) break;
// передача сообщений на сервер
sendto(my_sock, &buff[0], strlen(&buff[0]), 0, (sockaddr *)&dest_addr, sizeof(dest_addr));
// прием сообщения с сервера
sockaddr_in server_addr;
int server_addr_size = sizeof(server_addr);
int n = recvfrom(my_sock, &buff[0], sizeof(buff) - 1, 0, (sockaddr *)&server_addr, &server_addr_size);
if (n == SOCKET_ERROR)
{
cout << "recvfrom() error: " << WSAGetLastError() << endl;
freeWsaAndSocket(my_sock);
}
buff[n] = 0;
// Вывод принятого с сервера сообщения на экран
cout << "Server to Client: " << &buff[0] << endl;
}
// Шаг последний – выход
freeWsaAndSocket(my_sock);
}
Сервер и клиент после ввода строки:
С помощью программы Wireshark отследили такую передаваемую информацию: