在Linux环境下用C++做网络通信,其实有挺多路子可走。归根结底,核心就是那几套东西——既有系统级的经典方案,也有让人省心的封装库,甚至C++标准库本身也在慢慢补这块短板。下面就把主流的几种方式拆开聊聊。

首先绕不开的,必须是BSD套接字(Socket)API。这是Unix/Linux世界里网络通信的基石,几乎所有底层网络操作都基于它。用套接字可以轻松构建客户端和服务器,支持TCP和UDP两种模式:
TCP套接字提供可靠的、面向连接的字节流服务,适合需要保证数据完整送达的场景;UDP套接字则是不可靠的、无连接的消息传递服务,适合对实时性要求高但能容忍丢包的应用。
当然,直接操作BSD套接字有时会让人觉得繁琐——要处理各种结构体、错误码、系统调用。于是出现了不少高级封装库,比如Boost.Asio、libevent、libuv。这些库把底层的细节包装得更友好,提供了异步事件驱动、跨平台支持等能力,很多生产级项目都在用。
另外值得提一下C++标准库自身的网络支持。从C++11开始引入了头文件,提供了像IP地址操作这样的基本功能。但实话实说,标准库这块目前还很薄弱,真要完成完整的网络通信,还是得靠BSD套接字或第三方库。
下面直接上代码,看一个最简单的TCP通信例子,用的是最经典的BSD套接字方式。
TCP服务器:
#include
#include
#include
#include
#include
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
// 创建socket文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置socket选项
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
// 绑定socket到指定端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 读取数据
read(new_socket, buffer, 1024);
std::cout << "Message received: " << buffer << std::endl;
// 发送响应
send(new_socket, "Hello from server", 17, 0);
std::cout << "Response sent" << std::endl;
// 关闭套接字
close(new_socket);
close(server_fd);
return 0;
}
TCP客户端:
#include
#include
#include
#include
#include
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
// 创建socket文件描述符
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
std::cout << " Socket creation error ";
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
// 将IPv4地址从文本转换为二进制形式
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
std::cout << "Invalid address/ Address not supported ";
return -1;
}
// 连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
std::cout << "Connection Failed ";
return -1;
}
// 发送数据
send(sock, hello, strlen(hello), 0);
std::cout << "Hello message sent";
// 读取响应
read(sock, buffer, 1024);
std::cout << "Message received: " << buffer << std::endl;
// 关闭套接字
close(sock);
return 0;
}
这个例子里,服务器监听8080端口,客户端连上去后发一条消息。服务器收到消息后,回复一个“Hello from server”。整个过程虽然简单,但把网络通信的核心步骤都走了一遍——创建套接字、绑定、监听、接受连接、读写数据、关闭连接。
编译也很直接,用g++就可以:
g++ -o server server.cpp
g++ -o client client.cpp
然后分别运行服务器和客户端程序,就能看到效果了。当然,这只是一个入门级的演示,实际项目里还需要考虑错误处理、并发连接、协议设计等很多细节。不过把这个骨架跑通,后续再往上添功能就有底气了。