TCP and UDP client sockets - first version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 30 Jul 2022 23:25:23 +0200
branchv_0
changeset 9 de48b9278211
parent 8 3e17086fffea
child 10 6a6b93507856
TCP and UDP client sockets - first version
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<Socket> open(const SocketOptions& options) {
+		std::shared_ptr<UDPClientSocket> s = std::make_shared<UDPClientSocket>();
+		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<Socket> open(const SocketOptions& options) {
-		std::shared_ptr<UDPSocket> s = std::make_shared<UDPSocket>();
+		std::shared_ptr<TCPClientSocket> s = std::make_shared<TCPClientSocket>();
 		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<const char* protocol, const char* role, const char* mode, typename SocketClass>
@@ -100,19 +143,18 @@
 
 static std::vector<std::shared_ptr<SocketFactory>> factories
 {
-	// FIXME: different classes than UDPSocket
-	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPSocket >> (),
-	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPSocket >> (),
+	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
+	std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
+	std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+	std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
 };
 
 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {