# HG changeset patch # User František Kučera # Date 1659216323 -7200 # Node ID de48b927821149149dcd54ba64c9eb52ad3eb13b # Parent 3e17086fffea87c274a13ac8df4a42d132bbaea5 TCP and UDP client sockets - first version diff -r 3e17086fffea -r de48b9278211 src/Socket.cpp --- a/src/Socket.cpp Sat Jul 30 12:58:14 2022 +0200 +++ b/src/Socket.cpp Sat Jul 30 23:25:23 2022 +0200 @@ -57,13 +57,53 @@ } }; -class UDPSocket : public Socket { +static void check(int result, std::string message) { + if (result == 0); // OK + else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message); +} + +class UDPClientSocket : public Socket { +private: + struct sockaddr_in remoteAddress; + int protocol = IPPROTO_UDP; + int type = SOCK_DGRAM; +public: + + static std::shared_ptr open(const SocketOptions& options) { + std::shared_ptr s = std::make_shared(); + memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); + s->remoteAddress.sin_family = AF_INET; + s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) + s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); + + auto protocol = findOption(options, OPTION_PROTOCOL); + if (protocol == PROTOCOL_SCTP) { + s->protocol = IPPROTO_SCTP; + s->type = SOCK_SEQPACKET; + } + + return s; + } + + void send(const std::string& message) override { + FD s(::socket(AF_INET, type, protocol)); + sendto(s.getFD(), message.c_str(), message.size(), 0, (sockaddr*) & remoteAddress, sizeof (remoteAddress)); + } + + const std::string receive() override { + // TODO: TCP receive() + return "TODO: receive() a message"; + } + +}; + +class TCPClientSocket : public Socket { private: struct sockaddr_in remoteAddress; public: static std::shared_ptr open(const SocketOptions& options) { - std::shared_ptr s = std::make_shared(); + std::shared_ptr s = std::make_shared(); memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); s->remoteAddress.sin_family = AF_INET; s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) @@ -72,8 +112,10 @@ } void send(const std::string& message) override { - FD s(::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); - sendto(s.getFD(), message.c_str(), message.size(), 0, (sockaddr*) & remoteAddress, sizeof (remoteAddress)); + FD s(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); + check(::connect(s.getFD(), (sockaddr*) & remoteAddress, sizeof (remoteAddress)), "connect socket"); + ssize_t written = ::write(s.getFD(), message.c_str(), message.size()); + if (written != message.size()) throw std::logic_error("writing to the socket failed"); } const std::string receive() override { @@ -81,6 +123,7 @@ return "TODO: receive() a message"; } + }; template @@ -100,19 +143,18 @@ static std::vector> factories { - // FIXME: different classes than UDPSocket - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), - std::make_shared> (), + std::make_shared> (), + std::make_shared> (), // TODO: correct class + std::make_shared> (), + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class }; std::shared_ptr SocketFactory::find(const SocketOptions& options) {