下面是最经典的 TCP "回显服务器":客户端发什么,服务端原样回什么 。
1、服务端 server.cpp
cpp
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
int main() {
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket");
return 1;
}
// 允许端口快速复用(避免 TIME_WAIT 影响)
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) < 0) {
perror("bind");
close(listen_fd);
return 1;
}
if (listen(listen_fd, 5) < 0) {
perror("listen");
close(listen_fd);
return 1;
}
std::cout << "Server listening on port 8080...\n";
sockaddr_in client{};
socklen_t client_len = sizeof(client);
int conn_fd = accept(listen_fd, (sockaddr*)&client, &client_len);
if (conn_fd < 0) {
perror("accept");
close(listen_fd);
return 1;
}
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &client.sin_addr, ip, sizeof(ip));
std::cout << "Client connected: " << ip << ":" << ntohs(client.sin_port) << "\n";
char buf[1024];
while (true) {
ssize_t n = recv(conn_fd, buf, sizeof(buf), 0);
if (n == 0) {
std::cout << "Client disconnected.\n";
break;
}
if (n < 0) {
perror("recv");
break;
}
// 回显
ssize_t sent = send(conn_fd, buf, n, 0);
if (sent < 0) {
perror("send");
break;
}
}
close(conn_fd);
close(listen_fd);
return 0;
}
2、客户端 client.cpp
cpp
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <string>
int main() {
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return 1;
}
sockaddr_in server{};
server.sin_family = AF_INET;
server.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);
if (connect(fd, (sockaddr*)&server, sizeof(server)) < 0) {
perror("connect");
close(fd);
return 1;
}
std::cout << "Connected to server. Type messages:\n";
std::string line;
char buf[1024];
while (std::getline(std::cin, line)) {
if (line == "quit") break;
if (send(fd, line.data(), line.size(), 0) < 0) {
perror("send");
break;
}
ssize_t n = recv(fd, buf, sizeof(buf), 0);
if (n <= 0) {
std::cout << "Server closed.\n";
break;
}
std::cout << "echo: " << std::string(buf, buf + n) << "\n";
}
close(fd);
return 0;
}
3、编译运行(Linux)
cpp
g++ server.cpp -o server
g++ client.cpp -o client
./server
# 另开一个终端
./client