C++网络编程基础:面试官让我写一个socket通信,我连bind和listen的顺序都搞反了

发布时间:2026/7/18 5:05:17

C++网络编程基础:面试官让我写一个socket通信,我连bind和listen的顺序都搞反了 多线程板块聊完了。今天进入一个新的领域——网络编程。在机器人开发里网络通信无处不在。多台机器人之间的协作、机器人和云端服务器的通信、远程遥控、遥测数据上报都要走网络。即使你用ROS2的DDS通信底层也是socket。先讲个面试糗事。面试官让我手写一个简单的TCP服务器。我心想这有什么难的socket、bind、listen、accept、recv、send流程背得滚瓜烂熟。结果写的时候一紧张把bind和listen的顺序搞反了——先listen再bind。面试官看了一眼代码笑着说你确定这个顺序当时那个尴尬至今记忆犹新。TCP通信的基本流程TCP是面向连接的协议。通信双方分客户端和服务器端流程不一样。服务器端的流程#include sys/socket.h #include netinet/in.h #include unistd.h #include cstring // 1. 创建socket int serverFd socket(AF_INET, SOCK_STREAM, 0); // 2. 绑定地址和端口 struct sockaddr_in addr; addr.sin_family AF_INET; addr.sin_addr.s_addr INADDR_ANY; // 监听所有网卡 addr.sin_port htons(8080); // 端口8080 bind(serverFd, (struct sockaddr*)addr, sizeof(addr)); // 3. 开始监听 listen(serverFd, 5); // 5是等待队列的长度 // 4. 接受连接 struct sockaddr_in clientAddr; socklen_t clientLen sizeof(clientAddr); int clientFd accept(serverFd, (struct sockaddr*)clientAddr, clientLen); // 5. 收发数据 char buffer[1024]; int n recv(clientFd, buffer, sizeof(buffer), 0); send(clientFd, Hello!, 6, 0); // 6. 关闭 close(clientFd); close(serverFd);客户端的流程简单一些int clientFd socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serverAddr; serverAddr.sin_family AF_INET; serverAddr.sin_addr.s_addr inet_addr(192.168.1.100); serverAddr.sin_port htons(8080); connect(clientFd, (struct sockaddr*)serverAddr, sizeof(serverAddr)); send(clientFd, Hello Server!, 13, 0); char buffer[1024]; recv(clientFd, buffer, sizeof(buffer), 0);记住顺序服务器端是socket→bind→listen→accept→recv/send客户端是socket→connect→send/recv。bind必须在listen之前——你得先告诉系统我在哪个端口上等着然后才能开始监听。UDP通信UDP是无连接的不需要listen和accept。发就发收就收// UDP服务器 int fd socket(AF_INET, SOCK_DGRAM, 0); bind(fd, ...); char buffer[1024]; struct sockaddr_in clientAddr; socklen_t len sizeof(clientAddr); recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)clientAddr, len); sendto(fd, reply, 5, 0, (struct sockaddr*)clientAddr, len);UDP比TCP快但不可靠——包可能丢失、可能乱序。在机器人开发里实时性要求高但允许偶尔丢包的场景比如视频流、实时位姿用UDP比较多。需要可靠传输的场景比如控制指令、地图数据用TCP。在机器人开发中的应用多机器人协作的时候机器人之间需要通信。一个常见的架构是一台机器人当主节点其他机器人当从节点用TCP连接class RobotCommServer { int serverFd_; vectorint clientFds_; mutex mtx_; public: void start(int port) { serverFd_ socket(AF_INET, SOCK_STREAM, 0); // bind, listen... // 用线程池处理连接 thread([this] { while (true) { int clientFd accept(serverFd_, nullptr, nullptr); lock_guardmutex lock(mtx_); clientFds_.push_back(clientFd); } }).detach(); } void broadcast(const string msg) { lock_guardmutex lock(mtx_); for (int fd : clientFds_) { send(fd, msg.c_str(), msg.size(), 0); } } };ROS2底层的DDS通信虽然封装得很好但本质上也是socket通信。理解socket编程有助于你调试网络层面的问题——比如为什么消息延迟高了、为什么丢包了。面试中的关键考点TCP和UDP的区别TCP面向连接、可靠传输、保证顺序、有流量控制UDP无连接、不可靠、不保证顺序、速度快。三次握手和四次握手TCP建立连接要三次握手SYN→SYN-ACK→ACK断开要四次挥手FIN→ACK→FIN→ACK。为什么断开多一次因为TCP是全双工的每个方向的关闭是独立的。socket的阻塞和非阻塞有什么区别默认情况下socket是阻塞的——recv没有数据时会一直等。非阻塞模式下recv没有数据会立即返回-1EAGAIN。高性能服务器通常用非阻塞socket配合IO多路复用select/poll/epoll。给正在准备面试的你再补充一个面试中经常被问到的实战话题怎么调试网络通信问题。在机器人开发里网络通信出问题时最常用的排查工具是wireshark——它可以抓取所有经过网卡的数据包让你看到实际发送和接收的字节内容。如果不想安装wiresharktcpdump在命令行下也能抓包。另外在代码层面给每次send和recv加上日志打印数据长度和前几个字节的十六进制值能快速定位数据是否正确传输。还有一个容易被忽略的点TCP是流式协议没有消息边界。你发两次send各10字节接收方可能一次recv收到20字节也可能分两次各收到10字节。所以在设计通信协议时必须在应用层自己定义消息边界——通常用长度前缀或者特殊分隔符。面试时如果你能聊到TCP粘包问题和解决方案面试官会觉得你有实际的网络编程经验。网络编程在机器人面试里不算高频考点但偶尔会问。基本的socket流程要会写TCP和UDP的区别要能讲清楚。调试网络问题的时候wireshark抓包和netstat查看连接状态是两个最常用的手段建议也了解一下。如果你做的是ROS2开发面试官可能不会直接考socket但会问DDS的通信机制你了解吗。这时候如果你能提到底层是UDP组播做发现UDP单播做数据传输面试官会觉得你对底层有了解。下篇聊序列化与反序列化——protobuf在机器人通信中的应用。网络上传输的数据需要序列化成字节流接收方再反序列化回来。protobuf是机器人领域最常用的序列化方案。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第58篇 多线程之线程池设计——机器人系统中的标配组件 下一篇预告第60篇 序列化与反序列化——protobuf在机器人通信中的应用有任何问题欢迎评论区留言我会尽量回复。

相关新闻