Обмен в одном запуске в C++
Полный цикл в одном процессе требует двух
потоков: один ждет accept, другой вызывает
connect к 127.0.0.1 и порту
18080.
Сначала клиент пишет строку, затем читает ответ -
порядок важен, иначе стороны ждут друг друга.
Ответ сервера выведем на клиенте после recv
в буфер с явным размером. Оба потока свяжем через
join, каждый дескриптор закроем через
close:
#include <arpa/inet.h>
#include <chrono>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <netinet/in.h>
#include <string>
#include <sys/socket.h>
#include <thread>
#include <unistd.h>
int main() {
std::thread server([]() {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) {
return;
}
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(18080);
if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) {
close(listen_fd);
return;
}
if (bind(listen_fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
close(listen_fd);
return;
}
if (listen(listen_fd, 1) == -1) {
close(listen_fd);
return;
}
int peer_fd = accept(listen_fd, nullptr, nullptr);
if (peer_fd == -1) {
close(listen_fd);
return;
}
char buf[128];
ssize_t got = recv(peer_fd, buf, sizeof(buf) - 1, 0);
if (got != -1) {
buf[got] = '\0';
std::string reply = "status: done\n";
send(peer_fd, reply.c_str(), reply.size(), 0);
}
close(peer_fd);
close(listen_fd);
});
std::thread client([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
return;
}
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(18080);
if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) {
close(fd);
return;
}
if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
close(fd);
return;
}
const char* line = "go\n";
if (send(fd, line, std::strlen(line), 0) == -1) {
close(fd);
return;
}
char buf[128];
ssize_t got = recv(fd, buf, sizeof(buf) - 1, 0);
if (got != -1) {
buf[got] = '\0';
std::cout << buf;
}
close(fd);
});
server.join();
client.join();
return 0;
}
Сервер может добавить к ответу прочитанный текст. Клиент печатает готовую строку целиком - так видно, что обмен завершился в рамках одного запуска:
#include <arpa/inet.h>
#include <chrono>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <netinet/in.h>
#include <string>
#include <sys/socket.h>
#include <thread>
#include <unistd.h>
int main() {
std::thread server([]() {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1) {
return;
}
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(18080);
if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) {
close(listen_fd);
return;
}
if (bind(listen_fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
close(listen_fd);
return;
}
if (listen(listen_fd, 1) == -1) {
close(listen_fd);
return;
}
int peer_fd = accept(listen_fd, nullptr, nullptr);
if (peer_fd == -1) {
close(listen_fd);
return;
}
char buf[128];
ssize_t got = recv(peer_fd, buf, sizeof(buf) - 1, 0);
if (got != -1) {
buf[got] = '\0';
std::string reply = std::string("heard: ") + buf;
send(peer_fd, reply.c_str(), reply.size(), 0);
}
close(peer_fd);
close(listen_fd);
});
std::thread client([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
return;
}
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(18080);
if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) {
close(fd);
return;
}
if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
close(fd);
return;
}
const char* line = "wave\n";
if (send(fd, line, std::strlen(line), 0) == -1) {
close(fd);
return;
}
char buf[128];
ssize_t got = recv(fd, buf, sizeof(buf) - 1, 0);
if (got != -1) {
buf[got] = '\0';
std::cout << buf;
}
close(fd);
});
server.join();
client.join();
return 0;
}
Клиент отправляет "start\n" на
127.0.0.1 и печатает ответ
"begin: start", который формирует
сервер.
В консоли клиента после обмена должна быть строка
"ok", если сервер получил "check".