Labs 3 & 4 implementation
This commit is contained in:
parent
ca1cedae85
commit
65b6aedf86
@ -26,7 +26,7 @@ add_subdirectory(modules/streams)
|
||||
add_subdirectory(modules/sockets)
|
||||
|
||||
add_subdirectory(modules/asyncio)
|
||||
add_subdirectory(programs/lab4)
|
||||
add_subdirectory(programs/lab34)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PRIVATE exceptions threads sockets streams)
|
||||
|
||||
@ -44,7 +44,7 @@ namespace LdH {
|
||||
template<class prefix_printer_t, class routine_t>
|
||||
requires std::invocable<routine_t> && std::same_as<std::invoke_result_t<routine_t>, void>
|
||||
&& std::invocable<prefix_printer_t> && std::same_as<std::invoke_result_t<prefix_printer_t>, void>
|
||||
void run_catching(prefix_printer_t const &prefix_printer, routine_t const &routine) {
|
||||
void run_catching(prefix_printer_t const &prefix_printer, routine_t &routine) {
|
||||
try {
|
||||
routine();
|
||||
} catch (LdH::Exception const &e) {
|
||||
|
||||
@ -25,9 +25,9 @@ namespace LdH::Sockets::Berkeley {
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t e) { { s.connect(e) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t e) { { s.bind(e) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s) { { s.close() } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t c, char const *d) { { s.send_stream(c, d) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t c, char *d) { { s.recv_stream(c, d) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t c, char *d) { { s.recv_datagram(c, d) } -> std::same_as<typename ctx_t::address_t>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t *c, char const *d, bool r) { { s.send_stream(c, d, r) } -> std::same_as<bool>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t *c, char *d, bool r) { { s.recv_stream(c, d, r) } -> std::same_as<bool>; } &&
|
||||
requires(typename ctx_t::socket_t s, std::size_t *c, char *d) { { s.recv_datagram(c, d) } -> std::same_as<typename ctx_t::address_t>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t e, std::size_t c, char const *d) { { s.send_datagram(e, c, d) } -> std::same_as<void>; } &&
|
||||
requires(typename ctx_t::socket_t s, typename ctx_t::address_t *a) { { s.accept(a) } -> std::same_as<typename ctx_t::socket_t>; };
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ namespace LdH::Sockets::Berkeley {
|
||||
ServerDatagramSocket &operator=(ServerDatagramSocket &&other) noexcept = default;
|
||||
|
||||
public:
|
||||
Address<ctx_t> recvOneTruncating(std::size_t size, char *data) {
|
||||
Address<ctx_t> recvOneTruncating(std::size_t *size, char *data) {
|
||||
this->_start_usage();
|
||||
auto addr = this->_value.recv_datagram(size, data);
|
||||
this->_finish_usage();
|
||||
@ -199,7 +199,7 @@ namespace LdH::Sockets::Berkeley {
|
||||
|
||||
void sendOne(Address<ctx_t> destination, std::size_t size, char const *data) {
|
||||
this->_start_usage();
|
||||
this->_value.send_datagram(destination, size, data);
|
||||
this->_value.send_datagram(_addr_internals<ctx_t>::unwrap(destination), size, data);
|
||||
this->_finish_usage();
|
||||
}
|
||||
|
||||
@ -238,15 +238,15 @@ namespace LdH::Sockets::Berkeley {
|
||||
ClientDatagramSocket &operator=(ClientDatagramSocket &&other) noexcept = default;
|
||||
|
||||
public:
|
||||
void recvOneTruncating(std::size_t size, char *data) override {
|
||||
void recvOneTruncating(std::size_t *size, char *data) override {
|
||||
this->_start_usage();
|
||||
this->_value.recv_stream(size, data);
|
||||
this->_value.recv_stream(size, data, false);
|
||||
this->_finish_usage();
|
||||
}
|
||||
|
||||
void sendOne(std::size_t size, char const *data) override {
|
||||
this->_start_usage();
|
||||
this->_value.send_stream(size, data);
|
||||
this->_value.send_stream(&size, data, false);
|
||||
this->_finish_usage();
|
||||
}
|
||||
|
||||
|
||||
@ -208,16 +208,18 @@ namespace LdH::Sockets::Berkeley {
|
||||
|
||||
StreamSocket &operator=(StreamSocket &&other) noexcept = default;
|
||||
|
||||
void read(std::size_t size, char *data) override {
|
||||
bool read(std::size_t *size, char *data) override {
|
||||
this->_start_reading("Socket already read by another thread");
|
||||
this->_value.recv_stream(size, data);
|
||||
bool closed = this->_value.recv_stream(size, data, true);
|
||||
this->_finish_reading();
|
||||
return closed;
|
||||
}
|
||||
|
||||
void write(std::size_t size, char const *data) override {
|
||||
bool write(std::size_t *size, char const *data) override {
|
||||
this->_start_writing("Socket already written by another thread");
|
||||
this->_value.send_stream(size, data);
|
||||
bool closed = this->_value.send_stream(size, data, true);
|
||||
this->_finish_writing();
|
||||
return closed;
|
||||
}
|
||||
|
||||
void close() override {
|
||||
@ -261,7 +263,9 @@ namespace LdH::Sockets::Berkeley {
|
||||
typename ctx_t::socket_t raw = this->_value.accept(&addr_raw);
|
||||
this->_finish_reading();
|
||||
|
||||
if (addr != nullptr)
|
||||
*addr = std::move(_addr_internals<ctx_t>::wrap(addr_raw));
|
||||
|
||||
return _socket_internals<StreamSocket<ctx_t> >::wrap(std::move(raw));
|
||||
}
|
||||
|
||||
|
||||
@ -135,7 +135,8 @@ namespace LdH::Sockets {
|
||||
}
|
||||
|
||||
socket_t accept(address_t *addr) {
|
||||
SOCKET sock = ::accept(this->_value, reinterpret_cast<sockaddr *>(&(addr->_value)), nullptr);
|
||||
int addrlen = sizeof(sockaddr_storage);
|
||||
SOCKET sock = ::accept(this->_value, reinterpret_cast<sockaddr *>(&(addr->_value)), &addrlen);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
@ -149,27 +150,41 @@ namespace LdH::Sockets {
|
||||
}
|
||||
|
||||
|
||||
void send_stream(std::size_t size, char const *data) {
|
||||
bool send_stream(std::size_t *size, char const *data, bool repeat) {
|
||||
size_t expected_size = *size;
|
||||
*size = 0;
|
||||
while (true) {
|
||||
std::size_t sent_count = ::send(this->_value, data, size, 0);
|
||||
std::size_t sent_count = ::send(this->_value, data, expected_size, 0);
|
||||
if (sent_count == SOCKET_ERROR) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
data += sent_count;
|
||||
size -= sent_count;
|
||||
if (size <= 0) return;
|
||||
expected_size -= sent_count;
|
||||
*size += sent_count;
|
||||
if (expected_size <= 0) return false;
|
||||
if (!repeat) return false;
|
||||
}
|
||||
}
|
||||
|
||||
void recv_stream(std::size_t size, char *data) {
|
||||
bool recv_stream(std::size_t *size, char *data, bool repeat) {
|
||||
size_t expected_size = *size;
|
||||
*size = 0;
|
||||
while (true) {
|
||||
std::size_t sent_count = ::recv(this->_value, data, size, 0);
|
||||
if (sent_count == SOCKET_ERROR) {
|
||||
std::size_t read_count = ::recv(this->_value, data, expected_size, 0);
|
||||
switch (read_count) {
|
||||
case SOCKET_ERROR:
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
case 0:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
data += sent_count;
|
||||
size -= sent_count;
|
||||
if (size <= 0) return;
|
||||
data += read_count;
|
||||
expected_size -= read_count;
|
||||
*size += read_count;
|
||||
if (expected_size <= 0) return false;
|
||||
if (!repeat) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,13 +195,14 @@ namespace LdH::Sockets {
|
||||
}
|
||||
}
|
||||
|
||||
address_t recv_datagram(std::size_t size, char *data) {
|
||||
address_t recv_datagram(std::size_t *size, char *data) {
|
||||
address_t out;
|
||||
int out_size = sizeof(out);
|
||||
int sent_count = ::recvfrom(this->_value, data, size, 0, reinterpret_cast<sockaddr *>(&out), &out_size);
|
||||
int sent_count = ::recvfrom(this->_value, data, *size, 0, reinterpret_cast<sockaddr *>(&out), &out_size);
|
||||
if (sent_count == SOCKET_ERROR) {
|
||||
LdH::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
*size = sent_count;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@ import std;
|
||||
namespace LdH::Streams {
|
||||
export class OutputStream {
|
||||
public:
|
||||
virtual void write(std::size_t, char const *) = 0;
|
||||
virtual bool write(std::size_t *, char const *) = 0;
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
@ -14,7 +14,7 @@ namespace LdH::Streams {
|
||||
|
||||
export class InputStream {
|
||||
public:
|
||||
virtual void read(std::size_t, char *) = 0;
|
||||
virtual bool read(std::size_t *, char *) = 0;
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
@ -33,7 +33,7 @@ namespace LdH::Streams {
|
||||
|
||||
export class InputMessanger {
|
||||
public:
|
||||
virtual void recvOneTruncating(std::size_t, char *) = 0;
|
||||
virtual void recvOneTruncating(std::size_t *, char *) = 0;
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
|
||||
17
programs/lab34/CMakeLists.txt
Normal file
17
programs/lab34/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
add_library(lab34_ping_ OBJECT src/_ping.cpp src/variant.hpp)
|
||||
target_link_libraries(lab34_ping_ PRIVATE sockets exceptions)
|
||||
|
||||
add_executable(lab34_ping_tcp src/ping_tcp.cpp)
|
||||
target_link_libraries(lab34_ping_tcp PRIVATE lab34_ping_)
|
||||
|
||||
add_executable(lab34_ping_udp src/ping_udp.cpp)
|
||||
target_link_libraries(lab34_ping_udp PRIVATE lab34_ping_)
|
||||
|
||||
add_library(lab34_pong_ OBJECT ./src/pong.cpp src/variant.hpp)
|
||||
target_link_libraries(lab34_pong_ PRIVATE sockets exceptions)
|
||||
|
||||
add_executable(lab34_pong_tcp src/pong_tcp.cpp)
|
||||
target_link_libraries(lab34_pong_tcp PRIVATE lab34_pong_)
|
||||
|
||||
add_executable(lab34_pong_udp src/pong_udp.cpp)
|
||||
target_link_libraries(lab34_pong_udp PRIVATE lab34_pong_)
|
||||
104
programs/lab34/src/_ping.cpp
Normal file
104
programs/lab34/src/_ping.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
import std;
|
||||
import ru.landgrafhomyak.BGTU.networks_1.exceptions;
|
||||
import ru.landgrafhomyak.BGTU.networks_1.sockets;
|
||||
|
||||
#include "variant.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <Protocol>
|
||||
class PingVariant
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
class PingVariant<Protocol::TCP>
|
||||
{
|
||||
using socket_t = LdH::Sockets::StreamSocket;
|
||||
|
||||
static socket_t connect(LdH::Sockets::Address& addr)
|
||||
{
|
||||
return LdH::Sockets::connect_tcp(addr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <Protocol PING_TYPE>
|
||||
int ping_main(int argc, char const* const* argv)
|
||||
{
|
||||
int ret_v;
|
||||
bool was_error = true;
|
||||
LdH::run_catching_main([&]
|
||||
{
|
||||
if (argc != 3 && argc != 4)
|
||||
{
|
||||
std::cout << "Wrong CLI arguments count: " << (argc - 1) << "\n";
|
||||
std::cout << "Usage: " << argv[0] << " {dst_addr} {payload}" << std::endl;
|
||||
std::cout << "Usage: " << argv[0] << " {dst_addr} {port/service} {payload}" << std::endl;
|
||||
ret_v = 1, was_error = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t payload_size = std::strlen(argv[(argc == 3 ? 2 : 3)]);
|
||||
|
||||
if (payload_size > 255)
|
||||
{
|
||||
std::cout << "Payloand too long: " << payload_size << "\n";
|
||||
std::cout << "Maximum payload size is 255" << std::endl;
|
||||
ret_v = 1, was_error = false;
|
||||
return;
|
||||
}
|
||||
|
||||
char payload[256];
|
||||
payload[0] = static_cast<unsigned char>(payload_size);
|
||||
std::memcpy(payload + 1, argv[(argc == 3 ? 2 : 3)], payload_size);
|
||||
payload_size++;
|
||||
|
||||
|
||||
LdH::Sockets::init_sockets();
|
||||
auto dst = LdH::Sockets::Address::parse(argv[1], (argc == 3 ? nullptr : argv[2]));
|
||||
|
||||
|
||||
if constexpr (PING_TYPE == Protocol::TCP)
|
||||
{
|
||||
auto sock = LdH::Sockets::connect_tcp(dst);
|
||||
|
||||
sock.write(&payload_size, payload);
|
||||
std::cout << "Sent " << payload_size << " bytes\nReceiving:\n\n";
|
||||
std::cout.flush();
|
||||
|
||||
while (true)
|
||||
{
|
||||
char buff[1024];
|
||||
std::size_t buff_size = sizeof(buff);
|
||||
bool is_closed = sock.read(&buff_size, buff);
|
||||
std::cout << std::string{buff, buff_size};
|
||||
if (is_closed) break;
|
||||
}
|
||||
|
||||
sock.close();
|
||||
ret_v = 0, was_error = false;
|
||||
}
|
||||
else if constexpr (PING_TYPE == Protocol::UDP)
|
||||
{
|
||||
auto sock = LdH::Sockets::connect_udp(dst);
|
||||
|
||||
sock.sendOne(payload_size, payload);
|
||||
std::cout << "Sent " << payload_size << " bytes\nReceiving:\n\n";
|
||||
std::cout.flush();
|
||||
|
||||
char buff[65536];
|
||||
std::size_t buff_size = sizeof(buff);
|
||||
sock.recvOneTruncating(&buff_size, buff);
|
||||
std::cout << std::string{buff, buff_size};
|
||||
|
||||
sock.close();
|
||||
ret_v = 0, was_error = false;
|
||||
}
|
||||
LdH::Sockets::deinit_sockets();
|
||||
});
|
||||
|
||||
if (was_error)
|
||||
return 3;
|
||||
return ret_v;
|
||||
}
|
||||
5
programs/lab34/src/ping_tcp.cpp
Normal file
5
programs/lab34/src/ping_tcp.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "variant.hpp"
|
||||
|
||||
int main(int argc, char const *const*argv) {
|
||||
return ping_main<Protocol::TCP>(argc, argv);
|
||||
}
|
||||
5
programs/lab34/src/ping_udp.cpp
Normal file
5
programs/lab34/src/ping_udp.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "variant.hpp"
|
||||
|
||||
int main(int argc, char const *const*argv) {
|
||||
return ping_main<Protocol::UDP>(argc, argv);
|
||||
}
|
||||
160
programs/lab34/src/pong.cpp
Normal file
160
programs/lab34/src/pong.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
import std;
|
||||
import ru.landgrafhomyak.BGTU.networks_1.exceptions;
|
||||
import ru.landgrafhomyak.BGTU.networks_1.sockets;
|
||||
|
||||
#include "variant.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class ByteCounter
|
||||
{
|
||||
private:
|
||||
std::size_t bytes[std::numeric_limits<char>::max() - std::numeric_limits<char>::min() + 1];
|
||||
|
||||
public:
|
||||
ByteCounter() : bytes{}
|
||||
{
|
||||
for (auto& e : this->bytes)
|
||||
{
|
||||
e = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t& operator[](char c)
|
||||
{
|
||||
return this->bytes[c - std::numeric_limits<char>::min()];
|
||||
}
|
||||
|
||||
void apply(char const* payload, std::size_t count)
|
||||
{
|
||||
for (std::size_t i = 0; i < count; i++)
|
||||
this->operator[](payload[i])++;
|
||||
}
|
||||
|
||||
void print(std::ostream& out)
|
||||
{
|
||||
for (char c = std::numeric_limits<char>::min(); c < std::numeric_limits<char>::max(); c++)
|
||||
{
|
||||
if (this->operator[](c) != 0)
|
||||
{
|
||||
out << static_cast<int>(c) << ": " << this->operator[](c) << " times\n";
|
||||
}
|
||||
}
|
||||
if (this->operator[](std::numeric_limits<char>::max()) != 0)
|
||||
{
|
||||
out << static_cast<int>(std::numeric_limits<char>::max()) << ": " << this->operator[](
|
||||
std::numeric_limits<char>::max()) << " times\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void do_tcp(LdH::Sockets::Address& listen_addr)
|
||||
{
|
||||
auto server = LdH::Sockets::listen_tcp(listen_addr, 10);
|
||||
|
||||
while (true)
|
||||
{
|
||||
LdH::Sockets::Address addr;
|
||||
auto sock = server.wait_for_connection(&addr);
|
||||
std::cout << "Connection from " << addr.to_string() << std::endl;
|
||||
|
||||
std::size_t read_count;
|
||||
bool closed;
|
||||
|
||||
char payload_size;
|
||||
read_count = 1;
|
||||
closed = sock.read(&read_count, &payload_size);
|
||||
if (closed)
|
||||
{
|
||||
sock.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
char payload[255];
|
||||
read_count = static_cast<unsigned char>(payload_size);
|
||||
closed = sock.read(&read_count, payload);
|
||||
if (closed)
|
||||
{
|
||||
sock.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
ByteCounter counter;
|
||||
counter.apply(payload, read_count);
|
||||
|
||||
std::stringstream resp_builder;
|
||||
resp_builder << "Bytes summary:\n";
|
||||
counter.print(resp_builder);
|
||||
|
||||
auto resp = resp_builder.str();
|
||||
read_count = resp.length();
|
||||
|
||||
sock.write(&read_count, resp.c_str());
|
||||
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
|
||||
void do_udp(LdH::Sockets::Address& listen_addr)
|
||||
{
|
||||
auto server = LdH::Sockets::listen_udp(listen_addr);
|
||||
|
||||
while (true)
|
||||
{
|
||||
char payload[65536];
|
||||
std::size_t read_count = 65536;
|
||||
LdH::Sockets::Address addr = server.recvOneTruncating(&read_count, payload);
|
||||
|
||||
std::cout << "Connection from " << addr.to_string() << std::endl;
|
||||
|
||||
|
||||
ByteCounter counter;
|
||||
counter.apply(payload, read_count);
|
||||
|
||||
std::stringstream resp_builder;
|
||||
resp_builder << "Bytes summary:\n";
|
||||
counter.print(resp_builder);
|
||||
|
||||
auto resp = resp_builder.str();
|
||||
read_count = resp.length();
|
||||
|
||||
server.sendOne(addr, read_count, resp.c_str());
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
||||
template <Protocol PROTOCOL>
|
||||
int pong_main(int argc, char const* const* argv)
|
||||
{
|
||||
int ret_v;
|
||||
bool was_error = true;
|
||||
LdH::run_catching_main([&]
|
||||
{
|
||||
if (argc != 2 && argc != 3)
|
||||
{
|
||||
std::cout << "Wrong CLI arguments count: " << (argc - 1) << "\n";
|
||||
std::cout << "Usage: " << argv[0] << " {listen_addr}" << std::endl;
|
||||
std::cout << "Usage: " << argv[0] << " {listen_addr} {port/service}" << std::endl;
|
||||
ret_v = 1, was_error = false;
|
||||
return;
|
||||
}
|
||||
LdH::Sockets::init_sockets();
|
||||
|
||||
auto addr = LdH::Sockets::Address::parse(argv[1], (argc == 2 ? nullptr : argv[2]));
|
||||
|
||||
if constexpr (PROTOCOL == Protocol::TCP)
|
||||
{
|
||||
do_tcp(addr);
|
||||
}
|
||||
else if constexpr (PROTOCOL == Protocol::UDP)
|
||||
{
|
||||
do_udp(addr);
|
||||
}
|
||||
LdH::Sockets::deinit_sockets();
|
||||
});
|
||||
|
||||
if (was_error)
|
||||
return 3;
|
||||
return ret_v;
|
||||
}
|
||||
5
programs/lab34/src/pong_tcp.cpp
Normal file
5
programs/lab34/src/pong_tcp.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "variant.hpp"
|
||||
|
||||
int main(int argc, char const *const*argv) {
|
||||
return pong_main<Protocol::TCP>(argc, argv);
|
||||
}
|
||||
5
programs/lab34/src/pong_udp.cpp
Normal file
5
programs/lab34/src/pong_udp.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "variant.hpp"
|
||||
|
||||
int main(int argc, char const *const*argv) {
|
||||
return pong_main<Protocol::UDP>(argc, argv);
|
||||
}
|
||||
25
programs/lab34/src/variant.hpp
Normal file
25
programs/lab34/src/variant.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
enum class Protocol {
|
||||
TCP,
|
||||
UDP,
|
||||
};
|
||||
|
||||
template<Protocol>
|
||||
extern int ping_main(int argc, char const* const* argv);
|
||||
|
||||
template
|
||||
int ping_main<Protocol::TCP>(int, char const* const*);
|
||||
|
||||
template
|
||||
int ping_main<Protocol::UDP>(int, char const* const*);
|
||||
|
||||
|
||||
template<Protocol>
|
||||
extern int pong_main(int argc, char const* const* argv);
|
||||
|
||||
template
|
||||
int pong_main<Protocol::TCP>(int, char const* const*);
|
||||
|
||||
template
|
||||
int pong_main<Protocol::UDP>(int, char const* const*);
|
||||
@ -1,5 +0,0 @@
|
||||
add_executable(lab4_ping ./src/ping.cpp)
|
||||
add_executable(lab4_pong ./src/pong.cpp)
|
||||
|
||||
target_link_libraries(lab4_ping PRIVATE wsock32 ws2_32 exceptions asyncio)
|
||||
target_link_libraries(lab4_pong PRIVATE wsock32 ws2_32 exceptions asyncio)
|
||||
@ -1,80 +0,0 @@
|
||||
|
||||
#include <Winsock2.h>
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <LdH/exception.hpp>
|
||||
#include <LdH/asyncio.hpp>
|
||||
|
||||
|
||||
static void ping() {
|
||||
SOCKET sock = WSASocketW(
|
||||
AF_INET,
|
||||
SOCK_DGRAM,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
/*WSA_FLAG_OVERLAPPED | */WSA_FLAG_NO_HANDLE_INHERIT
|
||||
);
|
||||
if (sock == INVALID_SOCKET)
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
|
||||
|
||||
sockaddr selfaddr;
|
||||
INT selfaddrlen = sizeof(sockaddr);
|
||||
|
||||
if (SOCKET_ERROR == WSAStringToAddressW((wchar_t *) L"127.0.0.1:8082", AF_INET, nullptr, &selfaddr, &selfaddrlen))
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
|
||||
|
||||
while (true) {
|
||||
char buffer[1024] = "hello world";
|
||||
WSABUF buffers_meta[1] = {{1024, buffer}};
|
||||
sockaddr addr;
|
||||
INT addrlen = sizeof(sockaddr);
|
||||
DWORD flags = 0;/* MSG_PARTIAL*/
|
||||
|
||||
DWORD transferred_count;
|
||||
|
||||
auto res = WSASendTo(
|
||||
sock,
|
||||
buffers_meta, 1,
|
||||
&transferred_count,
|
||||
/* MSG_PARTIAL*/ 0,
|
||||
&selfaddr, selfaddrlen,
|
||||
nullptr, nullptr
|
||||
);
|
||||
if (res == SOCKET_ERROR) {
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
res = WSARecvFrom(
|
||||
sock,
|
||||
buffers_meta, 1,
|
||||
&transferred_count,
|
||||
&flags,
|
||||
&addr, &addrlen,
|
||||
nullptr, nullptr
|
||||
);
|
||||
if (res == SOCKET_ERROR) {
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
std::cout << buffer << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
WSADATA wsaData;
|
||||
auto wsa_init_res = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (wsa_init_res != ERROR_SUCCESS)
|
||||
LdH::Exception::throwFromWindowsErrCode(wsa_init_res);
|
||||
|
||||
ping();
|
||||
|
||||
|
||||
WSACleanup();
|
||||
} catch (LdH::Exception &e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
|
||||
#include <Winsock2.h>
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <LdH/exception.hpp>
|
||||
#include <LdH/asyncio.hpp>
|
||||
|
||||
|
||||
static void connections_listener() {
|
||||
SOCKET sock = WSASocketW(
|
||||
AF_INET,
|
||||
SOCK_DGRAM,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
/*WSA_FLAG_OVERLAPPED | */WSA_FLAG_NO_HANDLE_INHERIT
|
||||
);
|
||||
if (sock == INVALID_SOCKET)
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
|
||||
|
||||
sockaddr selfaddr;
|
||||
INT selfaddrlen = sizeof(sockaddr);
|
||||
|
||||
if (SOCKET_ERROR == WSAStringToAddressW((wchar_t *) L"127.0.0.1:8082", AF_INET, nullptr, &selfaddr, &selfaddrlen))
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
|
||||
if (SOCKET_ERROR == bind(sock, &selfaddr, selfaddrlen))
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
|
||||
|
||||
while (true) {
|
||||
char buffer[1024];
|
||||
WSABUF buffers_meta[1] = {{1024, buffer}};
|
||||
sockaddr addr;
|
||||
INT addrlen = sizeof(sockaddr);
|
||||
DWORD flags = 0;/* MSG_PARTIAL*/
|
||||
|
||||
DWORD transferred_count;
|
||||
auto res = WSARecvFrom(
|
||||
sock,
|
||||
buffers_meta, 1,
|
||||
&transferred_count,
|
||||
&flags,
|
||||
&addr, &addrlen,
|
||||
nullptr, nullptr
|
||||
);
|
||||
if (res == SOCKET_ERROR) {
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
|
||||
buffers_meta[0].len = transferred_count;
|
||||
std::cout << buffer << std::endl;
|
||||
|
||||
res = WSASendTo(
|
||||
sock,
|
||||
buffers_meta, 1,
|
||||
&transferred_count,
|
||||
/* MSG_PARTIAL*/ 0,
|
||||
&addr, sizeof(sockaddr),
|
||||
nullptr, nullptr
|
||||
);
|
||||
if (res == SOCKET_ERROR) {
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
WSADATA wsaData;
|
||||
auto wsa_init_res = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (wsa_init_res != ERROR_SUCCESS)
|
||||
LdH::Exception::throwFromWindowsErrCode(wsa_init_res);
|
||||
|
||||
connections_listener();
|
||||
|
||||
|
||||
WSACleanup();
|
||||
} catch (LdH::Exception &e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
|
||||
#include <Winsock2.h>
|
||||
#include <Windows.h>
|
||||
#include <LdH/exception.hpp>
|
||||
#include <LdH/asyncio.hpp>
|
||||
|
||||
struct request_t {
|
||||
char buffer[1024];
|
||||
WSABUF buffers_meta[1] = {{1024, buffer}};
|
||||
sockaddr addr;
|
||||
SOCKET socket;
|
||||
};
|
||||
|
||||
static void connections_listener(void *) {
|
||||
SOCKET server = WSASocketW(
|
||||
AF_INET,
|
||||
SOCK_DGRAM,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT
|
||||
);
|
||||
if (server == INVALID_SOCKET)
|
||||
LdH::Exception::throwFromWindowsErrCode(WSAGetLastError());
|
||||
|
||||
while (true) {
|
||||
auto req = new request_t{};
|
||||
req->socket = server;
|
||||
|
||||
LdH::Asyncio::WindowsOverlappedEventloop::overlappedCall(
|
||||
[&](LPOVERLAPPED o, LPOVERLAPPED_COMPLETION_ROUTINE ocr) -> DWORD {
|
||||
DWORD recived_count;
|
||||
auto res = WSARecvFrom(
|
||||
server,
|
||||
req->buffers_meta, 1,
|
||||
&recived_count,
|
||||
/* MSG_PARTIAL*/ nullptr,
|
||||
&req->addr, nullptr,
|
||||
o, reinterpret_cast<LPWSAOVERLAPPED_COMPLETION_ROUTINE>(ocr)
|
||||
);
|
||||
if (res == SOCKET_ERROR) {
|
||||
auto err = WSAGetLastError();
|
||||
if (err == WSA_IO_PENDING)
|
||||
return 0;
|
||||
LdH::Exception::throwFromWindowsErrCode(err);
|
||||
}
|
||||
return recived_count;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void answer(request_t *data) {
|
||||
LdH::Asyncio::WindowsOverlappedEventloop::overlappedCall(
|
||||
[&](LPOVERLAPPED o, LPOVERLAPPED_COMPLETION_ROUTINE ocr) -> DWORD {
|
||||
DWORD recived_count;
|
||||
auto res = WSASendTo(
|
||||
data->socket,
|
||||
data->buffers_meta, 1,
|
||||
&recived_count,
|
||||
/* MSG_PARTIAL*/ 0,
|
||||
&data->addr, sizeof(sockaddr),
|
||||
o, reinterpret_cast<LPWSAOVERLAPPED_COMPLETION_ROUTINE>(ocr)
|
||||
);
|
||||
if (res == SOCKET_ERROR) {
|
||||
auto err = WSAGetLastError();
|
||||
if (err == WSA_IO_PENDING)
|
||||
return 0;
|
||||
LdH::Exception::throwFromWindowsErrCode(err);
|
||||
}
|
||||
return recived_count;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
WSADATA wsaData;
|
||||
auto wsa_init_res = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (wsa_init_res != ERROR_SUCCESS)
|
||||
LdH::Exception::throwFromWindowsErrCode(wsa_init_res);
|
||||
|
||||
LdH::Asyncio::WindowsOverlappedEventloop eventloop{};
|
||||
eventloop.addTask<void>(&connections_listener, nullptr);
|
||||
eventloop.runUntilHasTasksAndNotInterrupted();
|
||||
|
||||
|
||||
WSACleanup();
|
||||
} catch (LdH::Exception &e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user