Урок 1. Сетевое взаимодействие. Сокеты и UDP #1

Open
alexander wants to merge 1 commits from lesson_01 into master
9 changed files with 384 additions and 0 deletions

21
lesson_01/client/udp.cpp Normal file
View File

@ -0,0 +1,21 @@
/*
* udp.cpp
*
* Created on: 10 авг. 2022 г.
* Author: alexander
*/
#include "udp.h"
#include "client.h"
int clientUDP()
{
azh::Client client;
client.createUDP(1991);
client.start();
return 0;
}

10
lesson_01/client/udp.h Normal file
View File

@ -0,0 +1,10 @@
/*
* udp.h
*
* Created on: 10 авг. 2022 г.
* Author: alexander
*/
#pragma once
int clientUDP();

View File

@ -0,0 +1,55 @@
/*
* address.h
*
* Created on: 9 авг. 2022 г.
* Author: alexander
*/
#pragma once
#include <string.h>
#include <netinet/in.h>
namespace azh
{
class Address
{
private:
struct sockaddr_in _addr;
unsigned int _len;
public:
Address(unsigned short int family, unsigned int addr, unsigned short int port)
{
memset(&_addr, 0, sizeof(_addr));
_len = sizeof(_addr);
_addr.sin_family = family;
_addr.sin_addr.s_addr = addr;
_addr.sin_port = htons(port);
}
Address()
{
memset(&_addr, 0, sizeof(_addr));
_len = sizeof(_addr);
}
Address(Address &address)
{
_addr = address._addr;
_len = address._len;
}
unsigned int& size()
{
return _len;
}
struct sockaddr_in& operator*()
{
return _addr;
}
};
}

View File

@ -0,0 +1,67 @@
/*
* client.h
*
* Created on: 10 авг. 2022 г.
* Author: alexander
*/
#pragma once
#include <socket.h>
#include <address.h>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXLINE 1024
namespace azh
{
class Client
{
private:
Socket _socket;
Address _address;
char _buffer[MAXLINE];
long int _recv_len;
public:
Client(Socket &socket, Address &address) :
_socket(socket), _address(address), _recv_len(0)
{
}
Client() :
_recv_len(0)
{
}
void createUDP(unsigned short int port)
{
_socket = { AF_INET, SOCK_DGRAM, IPPROTO_UDP };
_address = { AF_INET, INADDR_ANY, port };
}
void start()
{
while (true)
{
char message[MAXLINE];
message[MAXLINE] = '\0';
std::cin.getline(message, MAXLINE);
sendto(_socket, message, strlen(message), MSG_CONFIRM, reinterpret_cast<const sockaddr*>(&_address), _address.size());
_recv_len = recvfrom(_socket, _buffer, MAXLINE - 1, MSG_WAITALL, reinterpret_cast<sockaddr*>(&_address), &_address.size());
if (_recv_len > 0)
{
_buffer[_recv_len] = '\0';
std::cout << _buffer << std::endl;
}
}
}
};
}

127
lesson_01/headers/server.h Normal file
View File

@ -0,0 +1,127 @@
/*
* server.h
*
* Created on: 9 авг. 2022 г.
* Author: alexander
*/
#pragma once
#include <socket.h>
#include <address.h>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXLINE 1024
namespace azh
{
class Server
{
private:
Socket _socket;
Address _address;
Address _client;
char _buffer[MAXLINE];
bool _listenLoop;
long int _recv_len;
typedef void (*hPtr)(std::string buffer, Server &s);
class Hook
{
private:
std::string _command;
hPtr _handler;
public:
Hook(std::string command, hPtr handler) :
_command(command), _handler(handler)
{
}
void execute(std::string buffer, Server &s)
{
if (_command == "")
{
_handler(buffer, s);
}
else
{
auto pos = buffer.find_first_of(_command);
if (pos != std::string::npos && pos == 0)
{
_handler(buffer, s);
}
}
}
};
std::vector<Hook> _hooks;
void print(char *buffer)
{
std::string s_buffer(buffer);
std::cout << s_buffer;
}
public:
Server(Socket &socket, Address &address) :
_socket(socket), _address(address), _listenLoop(true), _recv_len(0)
{
}
Server() :
_listenLoop(true), _recv_len(0)
{
}
void createUDP(unsigned short int port)
{
_socket = { AF_INET, SOCK_DGRAM, IPPROTO_UDP };
_address = { AF_INET, INADDR_ANY, port };
}
void bind()
{
if (::bind(_socket, reinterpret_cast<const sockaddr*>(&_address), _address.size()) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
}
void listen()
{
while (_listenLoop)
{
_recv_len = recvfrom(_socket, _buffer, MAXLINE - 1, MSG_WAITALL, reinterpret_cast<sockaddr*>(&_client), &_client.size());
if (_recv_len > 0)
{
_buffer[_recv_len] = '\0';
std::for_each(_hooks.begin(), _hooks.end(), [&](Hook &hook)
{
hook.execute(_buffer, *this);
});
const char *answer = "Сообщение получено!";
sendto(_socket, answer, strlen(answer), MSG_CONFIRM, reinterpret_cast<const sockaddr*>(&_client), _client.size());
}
}
}
void registerHook(std::string command, hPtr handler)
{
_hooks.push_back( { command, handler });
}
void stop()
{
_listenLoop = false;
}
};
}

View File

@ -0,0 +1,48 @@
/*
* socket.h
*
* Created on: 9 авг. 2022 г.
* Author: alexander
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
namespace azh
{
class Socket
{
private:
int _sockfd;
public:
Socket(int domain, int type, int protocol)
{
if ((_sockfd = socket(domain, type, protocol)) < 0)
{
perror("socket creation failed");
exit(EXIT_FAILURE);
}
}
Socket(Socket &socket)
{
_sockfd = socket._sockfd;
}
Socket()
{
_sockfd = -1;
}
operator int()
{
return _sockfd;
}
};
}

19
lesson_01/main.cpp Normal file
View File

@ -0,0 +1,19 @@
/*
* main.cpp
*
* Created on: 10 авг. 2022 г.
* Author: alexander
*/
#include "server/udp.h"
#include "client/udp.h"
int main()
{
serverUDP();
// clientUDP();
return 0;
}

27
lesson_01/server/udp.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "server.h"
#include "udp.h"
void print(std::string buffer, azh::Server &s)
{
std::cout << buffer << std::endl;
}
void stop(std::string buffer, azh::Server &s)
{
s.stop();
}
int serverUDP()
{
azh::Server server;
server.createUDP(1991);
server.bind();
server.registerHook("", print);
server.registerHook("exit", stop);
server.listen();
return 0;
}

10
lesson_01/server/udp.h Normal file
View File

@ -0,0 +1,10 @@
/*
* udp.h
*
* Created on: 10 авг. 2022 г.
* Author: alexander
*/
#pragma once
int serverUDP();