编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第27章_网络编程.cpp -o t && ./t(需先 cd 测试/)
// 第27章测试:网络编程(本机端到端 TCP 回显)
// 说明:在同一进程内启动服务器线程和客户端线程,
// 用 127.0.0.1 随机端口完成完整通信验证。
// Termux 下系统调用可用;若沙箱禁止网络,请手动运行
// 书中的 server.cpp / client.cpp 验证。
#include <print>
#include <thread>
#include <string>
#include <string_view>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int failures = 0;
#define CHECK(expr) \
do { \
if (!(expr)) { \
++failures; \
std::println("FAIL 第{}行: {}", __LINE__, #expr); \
} \
} while (0)
int start_server(int port, std::string& received) {
int fd = ::socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) return -1;
int opt = 1;
::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if (::bind(fd, (sockaddr*)&addr, sizeof(addr)) < 0) { ::close(fd); return -1; }
if (::listen(fd, 4) < 0) { ::close(fd); return -1; }
// 服务器线程:接受一次连接,回显,退出
std::thread([fd, &received] {
int client = ::accept(fd, nullptr, nullptr);
if (client < 0) return;
char buf[1024];
ssize_t n = ::recv(client, buf, sizeof(buf), 0);
if (n > 0) {
received.assign(buf, n);
::send(client, buf, n, 0); // 回显
}
::close(client);
}).detach();
return fd;
}
int main() {
// 服务器监听随机端口(端口 0 = 系统分配,这里用固定 18926)
const int PORT = 18926;
std::string received;
int server_fd = start_server(PORT, received);
CHECK(server_fd >= 0);
if (server_fd < 0) { std::println("服务器启动失败(端口被占用?)"); return 1; }
// 客户端连接并发送
int cfd = ::socket(AF_INET, SOCK_STREAM, 0);
CHECK(cfd >= 0);
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(PORT);
bool connected = false;
for (int attempt = 0; attempt < 50 && !connected; ++attempt) {
if (::connect(cfd, (sockaddr*)&addr, sizeof(addr)) == 0) connected = true;
else std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
CHECK(connected);
const char* msg = "你好,服务器!";
CHECK(::send(cfd, msg, (int)std::strlen(msg), 0) > 0);
char buf[1024] = {};
ssize_t n = ::recv(cfd, buf, sizeof(buf), 0);
CHECK(n > 0);
std::string reply(buf, n);
std::println("客户端收到: {}", reply);
// 等待服务器线程处理完
std::this_thread::sleep_for(std::chrono::milliseconds(100));
CHECK(received == "你好,服务器!"); // 服务器收到的内容
CHECK(reply == "你好,服务器!"); // 回显内容
::close(cfd);
::close(server_fd);
if (failures == 0) std::println("全部通过");
return failures;
}