96SEO 2026-02-20 01:10 8
}
上周在生产环境遇到了这个问题,排查了2天才定位到原因。
今天分享一下完整的解决方案,希望帮大家避坑。
name="tableOfContents">目录
id="1.%E5%89%8D%E7%BD%AE%E8%AF%B4%E6%98%8E-toc"
id="2.%E5%9F%BA%E4%BA%8ETCP%E7%9A%84Socket%E7%BC%96%E7%A8%8B-toc"
id="2.1.%E5%85%B7%E4%BD%93%E6%AD%A5%E9%AA%A4-toc"
id="2.2.TCP%E7%BC%96%E7%A8%8B%E6%AD%A5%E9%AA%A4%E6%A0%B8%E5%BF%83%E7%89%B9%E7%82%B9-toc"
id="2.3.%E6%B3%A8%E6%84%8F-toc"
id="2.4.%E5%AE%9E%E7%8E%B0TCP%E7%BC%96%E7%A8%8B-toc"
id="2.5.%E6%B5%8B%E8%AF%95TCP%E7%BC%96%E7%A8%8B-toc"
id="3.%E5%9F%BA%E4%BA%8EUDP%E7%9A%84Socket%E7%BC%96%E7%A8%8B-toc"
id="3.1.%E5%85%B7%E4%BD%93%E6%AD%A5%E9%AA%A4-toc"
id="3.2.UDP%E7%BC%96%E7%A8%8B%E6%AD%A5%E9%AA%A4%E6%A0%B8%E5%BF%83%E7%89%B9%E7%82%B9-toc"
id="3.3.%E6%B3%A8%E6%84%8F-toc"
id="3.4.%E5%AE%9E%E7%8E%B0UDP%E7%BC%96%E7%A8%8B-toc"
id="3.5.%E6%B5%8B%E8%AF%95UDP%E7%BC%96%E7%A8%8B-toc"
name="tableOfContents">
本篇文章来分享一下Socket编程,主要了解TCP编程、UDP编程。
id="1.%E5%89%8D%E7%BD%AE%E8%AF%B4%E6%98%8E"
name="1.%E5%89%8D%E7%BD%AE%E8%AF%B4%E6%98%8E"
1)">Socket编程基于TCP/UDP协议的网络编程,是程序员写代码实现设备通信的具体步骤;
justify">2)所有网络通信都是服务端+客户端模式:服务端是提供数据/服务的一方,客户端是请求数据/服务的一方。
id="2.%E5%9F%BA%E4%BA%8ETCP%E7%9A%84Socket%E7%BC%96%E7%A8%8B"
name="2.%E5%9F%BA%E4%BA%8ETCP%E7%9A%84Socket%E7%BC%96%E7%A8%8B"
id="2.1.%E5%85%B7%E4%BD%93%E6%AD%A5%E9%AA%A4"
name="2.1.%E5%85%B7%E4%BD%93%E6%AD%A5%E9%AA%A4"
justify">TCP是C/S架构,核心:有连接、双向交互。
justify">【2】②启动监听对象,绑定IP地址+端口号 →
服务端开始在指定端口等待客户端连接;
justify">【6】④数据交换:收发数据(本质是网络流的读写)
justify">【4】②调用连接方法,连接指定的服务器(IP
+端口)
id="2.2.TCP%E7%BC%96%E7%A8%8B%E6%AD%A5%E9%AA%A4%E6%A0%B8%E5%BF%83%E7%89%B9%E7%82%B9"
name="2.2.TCP%E7%BC%96%E7%A8%8B%E6%AD%A5%E9%AA%A4%E6%A0%B8%E5%BF%83%E7%89%B9%E7%82%B9"
style="margin-left:
justify">2.2.TCP编程步骤核心特点
style="margin-left:
justify">1)必须先启动服务端,再启动客户端,否则客户端连接失败;
justify">2)建立连接后,服务端和客户端是一对一的专属通信,稳定可靠;
传输完成后,服务端和客户端还需要执行「关闭连接」,完成四次挥手。
justify">2)标注的数字(如【1】)是执行顺序,绝对不能颠倒!
id="2.4.%E5%AE%9E%E7%8E%B0TCP%E7%BC%96%E7%A8%8B"
name="2.4.%E5%AE%9E%E7%8E%B0TCP%E7%BC%96%E7%A8%8B"
style="margin-left:
使用本地测试,服务端是控制台程序,本地启动后,Unity客户端连127.0.0.1即可通信,完全免费、无网络限制、稳定。
src="https://i-blog.csdnimg.cn/direct/c4637172d78740b0afa83464fbf41b2b.png"
alt=""
src="https://i-blog.csdnimg.cn/direct/893ecd1b0cf2462faa55cb5cf1fa4c4b.png"
args){Console.WriteLine("TCP服务端:本地控制台服务端");Console.WriteLine("服务端已启动,监听端口:9999");Console.WriteLine("等待Unity客户端连接...\n");//【1】①创建监听对象TcpListener
server
9999);try{//【2】②启动监听server.Start();//【5】③阻塞等待客户端连接
(控制台不怕阻塞)Socket
server.AcceptSocket();Console.WriteLine($"[{DateTime.Now}]客户端连接成功!
客户端IP:{socket.RemoteEndPoint}");if
(socket.Connected){//【6】④数据交换:服务端【先发后收】NetworkStream
stream
NetworkStream(socket);StreamReader
reader
};//第一步:服务端发送消息给服务端Console.WriteLine("\n请输入要发送给Unity客户端的信息:");string
sendMsg
Console.ReadLine();writer.WriteLine(sendMsg);//StreamWriter有缓冲区,写入的数据会先存到缓冲区,不会立刻发送到网络,只有调用Flush()才会强制把缓冲区的所有数据发送出去,不写的话,数据发不出去,服务端就永远收不到消息writer.Flush();//清空缓冲区,必须写,否则数据发不出去Console.WriteLine($"[{DateTime.Now}]服务端已发送:{sendMsg}");//第二步:服务端接收服务端的消息string
recvMsg
reader.ReadLine();Console.WriteLine($"[{DateTime.Now}]服务端收到客户端消息:{recvMsg}");//关闭资源writer.Close();reader.Close();stream.Close();socket.Close();}}catch
(Exception
ex){Console.WriteLine($"[{DateTime.Now}]服务端异常:{ex.Message}"
);}finally{server.Stop();Console.WriteLine($"\n[{DateTime.Now}]服务端已关闭,按任意键退出...");Console.ReadKey();}}}
}
tipContent;//服务器配置(本地测试:本地控制台服务端)private
string
"127.0.0.1";//"tcpbin.com";private
int
transform.Find("TipContent").GetComponent
();connectBtn transform.Find("ConnectBtn").GetComponent
src="https://i-blog.csdnimg.cn/direct/c2e1a094954f44769aa9a8f2c0c88730.png"
alt=""
src="https://i-blog.csdnimg.cn/direct/1896a4eb77a3418d9c7928bc033a95d6.png"
width="1512">
最佳实践:
经过多个项目的验证,我总结了几个关键点:1)
做好异常处理
这些看似简单,但能避免很多生产环境问题。
2)在客户端点击“连接服务端”
src="https://i-blog.csdnimg.cn/direct/f597d2d20bbe4f0984a08758250ba6d5.png"
width="1563">
src="https://i-blog.csdnimg.cn/direct/e4357cf364274c379839f2324f781337.png"
width="1499">
3)在服务端输入要给客户端发送的信息,如:Hi,我是服务端!
客户端收到信息并回复后,服务端和客户端的连接断开。
src="https://i-blog.csdnimg.cn/direct/cbb3d77c97da482eace49be0f422e08b.png"
alt=""
src="https://i-blog.csdnimg.cn/direct/32fb9f9b05f74e41a47d9ebcf9e9ad90.png"
width="1512">
也可以使用免费公网TCP测试服务器,IP为tcpbin.com,端口为4242,该服务器的功能:发什么,它就原封不动给返回什么(回声服务器),适合测试TCP收发是否正常。
id="3.%E5%9F%BA%E4%BA%8EUDP%E7%9A%84Socket%E7%BC%96%E7%A8%8B"
name="3.%E5%9F%BA%E4%BA%8EUDP%E7%9A%84Socket%E7%BC%96%E7%A8%8B"
rgba(0,
id="3.1.%E5%85%B7%E4%BD%93%E6%AD%A5%E9%AA%A4"
name="3.1.%E5%85%B7%E4%BD%93%E6%AD%A5%E9%AA%A4"
style="margin-left:
1)">UDP无连接,步骤极简,核心:无连接、直接收发。
UDP没有服务端/客户端的严格区分,只有发送方/接收方,双方平等,无需建立连接。
id="3.2.UDP%E7%BC%96%E7%A8%8B%E6%AD%A5%E9%AA%A4%E6%A0%B8%E5%BF%83%E7%89%B9%E7%82%B9"
name="3.2.UDP%E7%BC%96%E7%A8%8B%E6%AD%A5%E9%AA%A4%E6%A0%B8%E5%BF%83%E7%89%B9%E7%82%B9"
style="margin-left:
justify">3.2.UDP编程步骤核心特点
style="margin-left:
justify">1)无需建立连接,没有握手和挥手,代码极简;
justify">2)发送方发完数据就完事,不管接收方是否在线、是否收到。
UDP无连接,客户端可以先发数据,服务端后接收;或者服务端先发,客户端后接收。
id="3.4.%E5%AE%9E%E7%8E%B0UDP%E7%BC%96%E7%A8%8B"
name="3.4.%E5%AE%9E%E7%8E%B0UDP%E7%BC%96%E7%A8%8B"
style="margin-left:
使用本地测试,服务端是控制台程序,本地启动后,Unity客户端连127.0.0.1即可通信,完全免费、无网络限制、稳定。
args){Console.WriteLine("UDP服务端:本地控制台服务端");Console.WriteLine("服务端绑定端口:8888
(接收客户端消息)");Console.WriteLine("客户端绑定端口:9999
serverListenPort
9999;//①创建创建监听对象//绑定8888端口,持续监听+发送UdpClient
udpServer
UdpClient(serverListenPort);IPEndPoint
clientPoint
IPEndPoint(IPAddress.Parse(clientIP),
clientListenPort);try{//②数据交换//1)作为接收方,接收数据//新开线程:持续监听8888端口,接收客户端发送的消息System.Threading.Thread
receiveThread
=>{//初始化在循环外,避免每次接收都重新创建,导致无法正确获取客户端地址IPEndPoint
remotePoint
Encoding.UTF8.GetString(recvBytes);Console.WriteLine($"\n[{DateTime.Now}]【收到客户端消息】:{recvInfo}");Console.WriteLine($"消息来源:{remotePoint}\n");}catch
}}});receiveThread.IsBackground
true;receiveThread.Start();//2)作为发送方,发送数据//主线程:持续输入内容,发送消息给客户端while
(true){Console.WriteLine("\n请输入要发送给客户端的消息:");string
sendInfo
Encoding.UTF8.GetBytes(sendInfo);udpServer.Send(sendBytes,
sendBytes.Length,
clientPoint);Console.WriteLine($"[{DateTime.Now}]服务端已发送:{sendInfo}
客户端({clientIP}:{clientListenPort})");}}catch
(Exception
ex){Console.WriteLine($"[{DateTime.Now}]发送失败:{ex.Message}");}finally{udpServer.Close();Console.WriteLine($"[{DateTime.Now}]服务端已关闭");}}}
}
inputMsg;//UDP配置:端口分离,永不冲突private
int
8888;//服务端的监听端口(给服务端发消息必须发这个端口)private
UdpClient
udpClient_Receive;//专门用于【接收】的UDP对象private
UdpClient
udpClient_Send;//专门用于【发送】的UDP对象private
void
transform.Find("TipContent").GetComponent
();sendBtn transform.Find("SendBtn").GetComponent
style="margin-left:
id="3.5.%E6%B5%8B%E8%AF%95UDP%E7%BC%96%E7%A8%8B"
name="3.5.%E6%B5%8B%E8%AF%95UDP%E7%BC%96%E7%A8%8B"
style="margin-left:
src="https://i-blog.csdnimg.cn/direct/554868b1920548e4927db7f80dd90a06.png"
alt=""
src="https://i-blog.csdnimg.cn/direct/af6778e1b97049ec8b11cb008bbfaa18.png"
width="1565">
2)客户端发数据,服务端接收
src="https://i-blog.csdnimg.cn/direct/19b344c9352f41ee8a25ec826602cd90.png"
alt=""
src="https://i-blog.csdnimg.cn/direct/fba69dd4231d4c15a20530635efca653.png"
width="1734">
3)服务端发数据,客户端接收
src="https://i-blog.csdnimg.cn/direct/ddccb4821a22443288d24bffd7b93522.png"
alt=""
src="https://i-blog.csdnimg.cn/direct/cb23ca235f664070a94ea4bfa2c5c54f.png"
justify">4.总结
style="margin-left:
justify">TCP:面向连接、可靠、有序、慢
想继续了解TCP和UDP可以参考【一文了解】TCP协议和UDP协议
好了,本次的分享到这里就结束啦,希望对你有所帮助~
class="post-meta-container">
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback