<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Socket on 鹿鸣青野的blog</title><link>https://www.sylgalaxy.xyz/tags/socket/</link><description>Recent content in Socket on 鹿鸣青野的blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 13 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.sylgalaxy.xyz/tags/socket/index.xml" rel="self" type="application/rss+xml"/><item><title>C++ 网络编程基础：Socket API 与 TCP 通信</title><link>https://www.sylgalaxy.xyz/posts/cpp-socket-networking-basics/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-socket-networking-basics/</guid><description>&lt;p&gt;围绕 Socket API 与 TCP/UDP 通信的核心概念、函数对照、示例代码与常见坑。&lt;/p&gt;
&lt;h2 id="核心概念速查"&gt;核心概念速查&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;关键点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Socket&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;网络通信端点&lt;/td&gt;
&lt;td&gt;文件描述符抽象&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TCP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;面向连接、可靠&lt;/td&gt;
&lt;td&gt;三次握手、四次挥手&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UDP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;无连接、不可靠&lt;/td&gt;
&lt;td&gt;快速、轻量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;sockaddr&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;通用地址结构&lt;/td&gt;
&lt;td&gt;IPv4/IPv6 统一接口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;字节序&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;大端/小端转换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;htons()&lt;/code&gt; &lt;code&gt;htonl()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="tcp-三次握手与四次挥手"&gt;TCP 三次握手与四次挥手&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;三次握手(建立连接):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──SYN────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ◀─SYN+Ack─ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──Ack────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;四次挥手(关闭连接):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──FIN────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ◀─Ack───── Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ◀─FIN───── Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──Ack────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="tcp-客户端-服务器模型"&gt;TCP 客户端-服务器模型&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;服务器: socket() → bind() → listen() → accept() → recv/send → close()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;客户端: socket() → connect() → send/recv → close()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="核心函数对照表"&gt;核心函数对照表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;函数&lt;/th&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;th&gt;参数要点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;创建套接字&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AF_INET, SOCK_STREAM, 0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bind()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;绑定地址&lt;/td&gt;
&lt;td&gt;套接字 + sockaddr_in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;listen()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;监听连接&lt;/td&gt;
&lt;td&gt;backlog 队列长度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;accept()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;接受连接&lt;/td&gt;
&lt;td&gt;返回新套接字描述符&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;connect()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;发起连接&lt;/td&gt;
&lt;td&gt;服务器地址&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;send/recv()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;发送/接收数据&lt;/td&gt;
&lt;td&gt;缓冲区 + 长度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;htons/htonl()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;主机→网络字节序&lt;/td&gt;
&lt;td&gt;short/long&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ntohs/ntohl()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;网络→主机字节序&lt;/td&gt;
&lt;td&gt;short/long&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="从-qt-到原生-socket"&gt;从 Qt 到原生 Socket&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Qt 写法&lt;/th&gt;
&lt;th&gt;原生等价物&lt;/th&gt;
&lt;th&gt;差异要点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;server.listen(QHostAddress::Any, 8080)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;socket()&lt;/code&gt; + &lt;code&gt;bind()&lt;/code&gt; + &lt;code&gt;listen()&lt;/code&gt; 三步&lt;/td&gt;
&lt;td&gt;Qt 一行帮你做三件事&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;newConnection&lt;/code&gt; 信号 → &lt;code&gt;nextPendingConnection()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;accept()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Qt 信号通知;原生阻塞死等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket-&amp;gt;connectToHost(&amp;quot;ip&amp;quot;, port)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inet_pton()&lt;/code&gt; + &lt;code&gt;connect()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IP 解析要自己做&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket-&amp;gt;write(bytes)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;send(fd, buf, len, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;返回值要检查,可能只发一半&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;readyRead&lt;/code&gt; 信号 → &lt;code&gt;readAll()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;recv(fd, buf, size, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;没有&amp;quot;就绪通知&amp;quot;,直接阻塞读&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;errorOccurred&lt;/code&gt; / &lt;code&gt;stateChanged&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检查返回值 + &lt;code&gt;errno&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;错误要手动判断&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QUdpSocket::writeDatagram/readDatagram&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sendto()/recvfrom()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;多一个对端地址参数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QHostAddress(&amp;quot;127.0.0.1&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sockaddr_in&lt;/code&gt; + &lt;code&gt;inet_pton()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字符串 IP 手动转结构体&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;端口字节序自动处理&lt;/td&gt;
&lt;td&gt;必须自己 &lt;code&gt;htons()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Qt 内部帮你转了&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;核心差异&lt;/strong&gt;：Qt 信号槽背后是「事件循环 + 就绪通知」(reactor 模式)。原生编程没有这个循环——要么阻塞死等，要么用线程，要么用 &lt;code&gt;select/epoll&lt;/code&gt; 自己搭事件循环。学原生网络的本质，就是把 Qt 隐藏的三件事（&lt;strong&gt;fd 管理、字节序、事件分发&lt;/strong&gt;）亲手做一遍。&lt;/p&gt;</description></item><item><title>C++ 服务部署实战：从源码到公网访问</title><link>https://www.sylgalaxy.xyz/posts/cpp-http-server-deploy/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-http-server-deploy/</guid><description>&lt;blockquote&gt;
&lt;p&gt;在一台 2C2G 的云服务器上实测：单文件 HTTP 服务器，&lt;code&gt;g++&lt;/code&gt; 编译，监听 8080 端口，从编译到公网访问全流程跑通。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="1-socket-七步流程"&gt;1. socket 七步流程&lt;/h2&gt;
&lt;p&gt;示例是一个约 60 行的单文件程序 &lt;code&gt;http_server.cpp&lt;/code&gt;，纯 Linux socket API、零第三方依赖，放在你自己的项目目录里即可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;socket() → bind() → listen() → accept() → recv() → send() → close()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 建电话 插网线 开机待命 接电话 听需求 答复 挂断
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;步骤&lt;/th&gt;
&lt;th&gt;调用&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;socket(AF_INET, SOCK_STREAM, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IPv4 + TCP，返回文件描述符（Linux 一切皆文件）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bind(fd, &amp;amp;addr, sizeof)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;绑定地址；&lt;code&gt;INADDR_ANY&lt;/code&gt;（0.0.0.0）= 监听所有网卡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;listen(fd, 16)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;开始待命；16 是 backlog 等待队列长度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;accept(fd, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;阻塞等客户端，返回新 fd（每客户一个）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;recv(fd, buf, n, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读 HTTP 请求报文（原始文本）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;send(fd, resp, len, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;回 HTTP 响应&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;close(fd)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;挂断，回 while 等下一客&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;要点：&lt;/p&gt;</description></item></channel></rss>