Skip to content

Commit 5a9d6ef

Browse files
committed
Add simple TCP CLient
1 parent 72aa7eb commit 5a9d6ef

4 files changed

Lines changed: 138 additions & 0 deletions

File tree

src/socket/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ set(SOCKET_SOURCES
33
# Socket
44
${CMAKE_CURRENT_SOURCE_DIR}/simple_tcp/TCPServer.cpp
55
${CMAKE_CURRENT_SOURCE_DIR}/simple_tcp/SimpleTCPServer.cpp
6+
${CMAKE_CURRENT_SOURCE_DIR}/simple_tcp/TCPClient.cpp
7+
${CMAKE_CURRENT_SOURCE_DIR}/simple_tcp/SimpleTCPClient.cpp
68
)
79

810
set(SOCKET_SOURCES ${SOCKET_SOURCES} PARENT_SCOPE)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <iostream>
2+
#include "ExampleRegistry.h"
3+
#include "TCPClient.h"
4+
5+
namespace {
6+
7+
void run() {
8+
try {
9+
TCPClient client("127.0.0.1", 8080);
10+
11+
if (!client.connect()) {
12+
std::cout << "connect failed\n";
13+
return;
14+
}
15+
16+
client.send("Hello server\n");
17+
18+
std::string response = client.receive();
19+
20+
std::cout << "server: " << response << std::endl;
21+
22+
client.close();
23+
} catch (const std::exception& e) {
24+
std::cout << "error: " << e.what() << std::endl;
25+
}
26+
}
27+
28+
} // namespace
29+
30+
class SimpleTCPClient : public IExample {
31+
public:
32+
std::string group() const override { return "socket/tcp"; }
33+
34+
std::string name() const override { return "SimpleTCPClient"; }
35+
36+
std::string description() const override { return "Simple TCP Client"; }
37+
38+
void execute() override { run(); }
39+
};
40+
41+
REGISTER_EXAMPLE(SimpleTCPClient, "socket/tcp", "SimpleTCPClient");
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include "TCPClient.h"
2+
3+
#include <sys/socket.h>
4+
#include <stdexcept>
5+
6+
#include <arpa/inet.h>
7+
#include <netinet/in.h>
8+
#include <unistd.h>
9+
10+
TCPClient::TCPClient(const std::string& host, uint16_t port)
11+
: host_{host}, port_{port}, client_fd_{-1} {}
12+
13+
bool TCPClient::connect() {
14+
client_fd_ = socket(AF_INET, SOCK_STREAM, 0);
15+
if (client_fd_ < 0) {
16+
throw std::runtime_error("socket failed.");
17+
}
18+
19+
// specifying the address
20+
sockaddr_in serverAddress{};
21+
serverAddress.sin_family = AF_INET;
22+
serverAddress.sin_port = htons(port_);
23+
24+
// serverAddress.sin_addr.s_addr = INADDR_ANY;
25+
if (::inet_pton(AF_INET, host_.c_str(), &serverAddress.sin_addr) <= 0) {
26+
throw std::runtime_error("invalid address");
27+
}
28+
29+
// sending connection request
30+
return (
31+
::connect(client_fd_,
32+
reinterpret_cast<sockaddr*>(&serverAddress), // global syscall
33+
sizeof(serverAddress)) == 0);
34+
}
35+
36+
void TCPClient::send(const std::string& msg) {
37+
if (client_fd_ < 0) {
38+
throw std::runtime_error("socket not connected");
39+
}
40+
41+
const char* data = msg.c_str();
42+
size_t total = 0;
43+
size_t len = msg.size();
44+
while (total < len) {
45+
ssize_t sent = ::send(client_fd_, data + total, len - total, 0);
46+
if (sent <= 0) {
47+
throw std::runtime_error("send failed");
48+
}
49+
total += sent;
50+
}
51+
}
52+
53+
std::string TCPClient::receive() {
54+
if (client_fd_ < 0) {
55+
throw std::runtime_error("socket not connected");
56+
}
57+
58+
char buffer[1024];
59+
60+
ssize_t bytes = recv(client_fd_, buffer, sizeof(buffer), 0);
61+
if (bytes < 0) {
62+
throw std::runtime_error("recv failed");
63+
}
64+
65+
if (bytes == 0) {
66+
throw std::runtime_error("connection closed");
67+
}
68+
69+
return std::string(buffer, bytes);
70+
}
71+
72+
void TCPClient::close() {
73+
if (client_fd_ >= 0) {
74+
::close(client_fd_);
75+
client_fd_ = -1;
76+
}
77+
}

src/socket/simple_tcp/TCPClient.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
#include <stdint.h>
3+
#include <string>
4+
5+
class TCPClient {
6+
public:
7+
TCPClient(const std::string& host, uint16_t port);
8+
9+
bool connect();
10+
void close();
11+
void send(const std::string& msg);
12+
std::string receive();
13+
14+
private:
15+
std::string host_;
16+
uint16_t port_;
17+
int client_fd_;
18+
};

0 commit comments

Comments
 (0)