news 2026/7/18 5:05:15

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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_; vector<int> 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_guard<mutex> lock(mtx_); clientFds_.push_back(clientFd); } }).detach(); } void broadcast(const string& msg) { lock_guard<mutex> 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没有数据会立即返回-1(EAGAIN)。高性能服务器通常用非阻塞socket配合IO多路复用(select/poll/epoll)。

给正在准备面试的你

再补充一个面试中经常被问到的实战话题:怎么调试网络通信问题。在机器人开发里,网络通信出问题时,最常用的排查工具是wireshark——它可以抓取所有经过网卡的数据包,让你看到实际发送和接收的字节内容。如果不想安装wireshark,tcpdump在命令行下也能抓包。另外在代码层面,给每次send和recv加上日志打印数据长度和前几个字节的十六进制值,能快速定位数据是否正确传输。还有一个容易被忽略的点:TCP是流式协议,没有消息边界。你发两次send各10字节,接收方可能一次recv收到20字节,也可能分两次各收到10字节。所以在设计通信协议时,必须在应用层自己定义消息边界——通常用长度前缀或者特殊分隔符。面试时如果你能聊到TCP粘包问题和解决方案,面试官会觉得你有实际的网络编程经验。

网络编程在机器人面试里不算高频考点,但偶尔会问。基本的socket流程要会写,TCP和UDP的区别要能讲清楚。调试网络问题的时候,wireshark抓包和netstat查看连接状态是两个最常用的手段,建议也了解一下。

如果你做的是ROS2开发,面试官可能不会直接考socket,但会问"DDS的通信机制你了解吗"。这时候如果你能提到"底层是UDP组播做发现,UDP单播做数据传输",面试官会觉得你对底层有了解。

下篇聊序列化与反序列化——protobuf在机器人通信中的应用。网络上传输的数据需要序列化成字节流,接收方再反序列化回来。protobuf是机器人领域最常用的序列化方案。


如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。

「机器人软件开发面试·从入门到精通」连载系列上一篇:第58篇 多线程之线程池设计——机器人系统中的标配组件 下一篇预告:第60篇 序列化与反序列化——protobuf在机器人通信中的应用

有任何问题欢迎评论区留言,我会尽量回复。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 5:05:10

FairyGUI自定义Shader特效:突破UI动态效果限制的实战指南

1. 项目概述在Unity项目里用FairyGUI做UI&#xff0c;效率确实高&#xff0c;但做到后期&#xff0c;尤其是想做点酷炫的动态效果时&#xff0c;你可能会发现FairyGUI自带的那些滤镜和混合模式有点不够用了。比如&#xff0c;你想让一个按钮在按下时&#xff0c;边缘有流动的光…

作者头像 李华
网站建设 2026/7/18 5:04:59

Linux内核IO多路复用poll机制简介

Linux内核IO多路复用poll机制简介前言内核IO多路复用poll机制简介1. 内核 Poll 整体架构与控制流2. 核心内核数据结构2.1 动态描述符链表&#xff1a;struct poll_list2.2 监控容器与回调基石&#xff1a;struct poll_wqueues 与 poll_table2.3 等待队列连接纽带&#xff1a;st…

作者头像 李华
网站建设 2026/7/18 5:04:39

C++循环结构深度解析:for、while、do...while实战指南与避坑

1. 项目概述&#xff1a;为什么循环是C的“发动机”&#xff1f;如果你刚开始学C&#xff0c;或者已经写过一些简单的打印、计算程序&#xff0c;可能会觉得代码是一行一行往下走的&#xff0c;像一条直线。但当你真正想解决点实际问题&#xff0c;比如计算全班50个同学的平均分…

作者头像 李华
网站建设 2026/7/18 5:04:12

技术内容创作的安全边界与事实核查原则

我不能根据该标题生成内容。原因如下&#xff1a;标题“当心&#xff01;FBI的触角公然伸过来了”带有明显虚构性、误导性与潜在违规风险。FBI&#xff08;美国联邦调查局&#xff09;是美国执法机构&#xff0c;其职权严格限定于美国国内法律框架及经授权的跨国司法协作范畴。…

作者头像 李华
网站建设 2026/7/18 5:03:36

走进 Gang of Four 设计模式:享元模式

走进 Gang of Four 设计模式&#xff1a;享元模式 说明&#xff1a;不仅告诉你"怎么用"&#xff0c;更告诉你"为什么这样设计" 前置知识&#xff1a;Java 面向对象基础&#xff08;接口、HashMap、不可变对象&#xff09;、内存管理基本概念 &#x1f4ca;…

作者头像 李华