本文作者张彦飞,原题“聊聊TCP连接耗时的那些事儿”,有少许改动。

1、引言

对于基于互联网的通信应用(比如IM聊天、推送系统),数据传递时使用TCP协议相对较多。这是因为在TCP/IP协议簇的传输层协议中,TCP协议具备可靠的连接、错误重传、拥塞控制等优点,所以目前在应用场景上比UDP更广泛一些。

相信你也一定听闻过TCP也存在一些缺点,能常都是老生常谈的开销要略大。但是各路技术博客里都在单单说开销大、或者开销小,而少见不给出具体的量化分析。不客气的讲,类似论述都是没什么营养的废话。

经过日常工作的思考之后,我更想弄明白的是,TCP的开销到底有多大,能否进行量化。一条TCP连接的建立需要耗时延迟多少,是多少毫秒,还是多少微秒?能不能有一个哪怕是粗略的量化估计?当然影响TCP耗时的因素有很多,比如网络丢包等等。我今天只分享我在工作实践中遇到的比较高发的各种情况。

写在前面:得益于Linux内核的开源,本文中所提及的底层以及具体的内核级代码例子,都是以Linux系统为例。

学习交流:

(本文已同步发布于:http://www.52im.net/thread-3265-1-1.html

2、系列文章

本文是系列文章中的第11篇,本系列文章的大纲如下:

  1. 不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)
  2. 不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)
  3. 不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT
  4. 不为人知的网络编程(四):深入研究分析TCP的异常关闭
  5. 不为人知的网络编程(五):UDP的连接性和负载均衡
  6. 不为人知的网络编程(六):深入地理解UDP协议并用好它
  7. 不为人知的网络编程(七):如何让不可靠的UDP变的可靠?
  8. 不为人知的网络编程(八):从数据传输层深度解密HTTP
  9. 不为人知的网络编程(九):理论联系实际,全方位深入理解DNS
  10. 不为人知的网络编程(十):深入操作系统,从内核理解网络包的接收过程(Linux篇)
  11. 不为人知的网络编程(十一):从底层入手,深度分析TCP连接耗时的秘密》(本文)
  12. 不为人知的网络编程(十二):彻底搞懂TCP协议层的KeepAlive保活机制
  13. 不为人知的网络编程(十三):深入操作系统,彻底搞懂127.0.0.1本机网络通信
  14. 不为人知的网络编程(十四):拔掉网线再插上,TCP连接还在吗?一文即懂!

3、理想情况下的TCP连接耗时分析

要想搞清楚TCP连接的耗时,我们需要详细了解连接的建立过程。

在前文《深入操作系统,从内核理解网络包的接收过程(Linux篇)》中我们介绍了数据包在接收端是怎么被接收的:数据包从发送方出来,经过网络到达接收方的网卡;在接收方网卡将数据包DMA到RingBuffer后,内核经过硬中断、软中断等机制来处理(如果发送的是用户数据的话,最后会发送到socket的接收队列中,并唤醒用户进程)。

在软中断中,当一个包被内核从RingBuffer中摘下来的时候,在内核中是用struct sk_buff结构体来表示的(参见内核代码include/linux/skbuff.h)。其中的data成员是接收到的数据,在协议栈逐层被处理的时候,通过修改指针指向data的不同位置,来找到每一层协议关心的数据。

对于TCP协议包来说,它的Header中有一个重要的字段-flags。

如下图:

通过设置不同的标记位,将TCP包分成SYNC、FIN、ACK、RST等类型:

  • 1)客户端通过connect系统调用命令内核发出SYNC、ACK等包来实现和服务器TCP连接的建立;
  • 2)在服务器端,可能会接收许许多多的连接请求,内核还需要借助一些辅助数据结构-半连接队列和全连接队列。

我们来看一下整个连接过程:

在这个连接过程中,我们来简单分析一下每一步的耗时:

  • 1)客户端发出SYNC包:客户端一般是通过connect系统调用来发出SYN的,这里牵涉到本机的系统调用和软中断的CPU耗时开销;
  • 2)SYN传到服务器:SYN从客户端网卡被发出,开始“跨过山和大海,也穿过人山人海......”,这是一次长途远距离的网络传输;
  • 3)服务器处理SYN包:内核通过软中断来收包,然后放到半连接队列中,然后再发出SYN/ACK响应。又是CPU耗时开销;
  • 4)SYC/ACK传到客户端:SYC/ACK从服务器端被发出后,同样跨过很多山、可能很多大海来到客户端。又一次长途网络跋涉;
  • 5)客户端处理SYN/ACK:客户端内核收包并处理SYN后,经过几us的CPU处理,接着发出ACK。同样是软中断处理开销;
  • 6)ACK传到服务器:和SYN包,一样,再经过几乎同样远的路,传输一遍。 又一次长途网络跋涉;
  • 7)服务端收到ACK:服务器端内核收到并处理ACK,然后把对应的连接从半连接队列中取出来,然后放到全连接队列中。一次软中断CPU开销;
  • 8)服务器端用户进程唤醒:正在被accpet系统调用阻塞的用户进程被唤醒,然后从全连接队列中取出来已经建立好的连接。一次上下文切换的CPU开销。

以上几步操作,可以简单划分为两类:

  • 第一类:是内核消耗CPU进行接收、发送或者是处理,包括系统调用、软中断和上下文切换。它们的耗时基本都是几个us左右;
  • 第二类:是网络传输,当包被从一台机器上发出以后,中间要经过各式各样的网线、各种交换机路由器。所以网络传输的耗时相比本机的CPU处理,就要高的多了。根据网络远近一般在几ms~到几百ms不等。

1ms就等于1000us,因此网络传输耗时比双端的CPU开销要高1000倍左右,甚至更高可能还到100000倍。

所以:在正常的TCP连接的建立过程中,一般考虑网络延时即可。

PS:一个RTT指的是包从一台服务器到另外一台服务器的一个来回的延迟时间。

所以从全局来看:TCP连接建立的网络耗时大约需要三次传输,再加上少许的双方CPU开销,总共大约比1.5倍RTT大一点点。

不过,从客户端视角来看:只要ACK包发出了,内核就认为连接是建立成功了。所以如果在客户端打点统计TCP连接建立耗时的话,只需要两次传输耗时-既1个RTT多一点的时间。(对于服务器端视角来看同理,从SYN包收到开始算,到收到ACK,中间也是一次RTT耗时)。

4、极端情况下的TCP连接耗时分析

上一节可以看到:在客户端视角,正常情况下一次TCP连接总的耗时也就就大约是一次网络RTT的耗时。如果所有的事情都这么简单,我想我的这次分享也就没有必要了。事情不一定总是这么美好,意外的发生在所难免。

在某些情况下,可能会导致TCP连接时的网络传输耗时上涨、CPU处理开销增加、甚至是连接失败。本节将就我在线上遇到过的各种切身体会的沟沟坎坎,来分析一下极端情况下的TCP连接耗时情况。

4.1 客户端connect调用耗时失控案例

正常一个系统调用的耗时也就是几个us(微秒)左右。但是在我的《追踪将服务器CPU耗光的凶手!》一文中,笔者的一台服务器当时遇到一个状况:某次运维同学转达过来说该服务CPU不够用了,需要扩容。

当时的服务器监控如下图:

该服务之前一直每秒抗2000左右的qps,CPU的idel一直有70%+,怎么突然就CPU一下就不够用了呢。

而且更奇怪的是CPU被打到谷底的那一段时间,负载却并不高(服务器为4核机器,负载3-4是比较正常的)。

后来经过排查以后发现当TCP客户端TIME_WAIT有30000左右,导致可用端口不是特别充足的时候,connect系统调用的CPU开销直接上涨了100多倍,每次耗时达到了2500us(微秒),达到了毫秒级别。

当遇到这种问题的时候,虽然TCP连接建立耗时只增加了2ms左右,整体TCP连接耗时看起来还可接受。但这里的问题在于这2ms多都是在消耗CPU的周期,所以问题不小。

解决起来也非常简单,办法很多:修改内核参数net.ipv4.ip_local_port_range多预留一些端口号、改用长连接都可以。

4.2 TCP半/全连接队列满的案例

如果连接建立的过程中,任意一个队列满了,那么客户端发送过来的syn或者ack就会被丢弃。客户端等待很长一段时间无果后,然后会发出TCP Retransmission重传。

拿半连接队列举例:

要知道的是上面TCP握手超时重传的时间是秒级别的。也就是说一旦server端的连接队列导致连接建立不成功,那么光建立连接就至少需要秒级以上。而正常的在同机房的情况下只是不到1毫秒的事情,整整高了1000倍左右。

尤其是对于给用户提供实时服务的程序来说,用户体验将会受到较大影响。如果连重传也没有握手成功的话,很可能等不及二次重试,这个用户访问直接就超时了。

还有另外一个更坏的情况是:它还有可能会影响其它的用户。

假如你使用的是进程/线程池这种模型提供服务,比如:php-fpm。我们知道fpm进程是阻塞的,当它响应一个用户请求的时候,该进程是没有办法再响应其它请求的。假如你开了100个进程/线程,而某一段时间内有50个进程/线程卡在和redis或者mysql服务器的握手连接上了(注意:这个时候你的服务器是TCP连接的客户端一方)。这一段时间内相当于你可以用的正常工作的进程/线程只有50个了。而这个50个worker可能根本处理不过来,这时候你的服务可能就会产生拥堵。再持续稍微时间长一点的话,可能就产生雪崩了,整个服务都有可能会受影响。

既然后果有可能这么严重,那么我们如何查看我们手头的服务是否有因为半/全连接队列满的情况发生呢?

在客户端:可以抓包查看是否有SYN的TCP Retransmission。如果有偶发的TCP Retransmission,那就说明对应的服务端连接队列可能有问题了。

在服务端的话:查看起来就更方便一些了。netstat -s 可查看到当前系统半连接队列满导致的丢包统计,但该数字记录的是总丢包数。你需要再借助 watch 命令动态监控。如果下面的数字在你监控的过程中变了,那说明当前服务器有因为半连接队列满而产生的丢包。你可能需要加大你的半连接队列的长度了。

$ watch'netstat -s | grep LISTEN'

8 SYNs to LISTEN sockets ignored

对于全连接队列来说呢,查看方法也类似:

$ watch'netstat -s  | grep overflowed'

160 timesthe listen queue of a socket overflowed

如果你的服务因为队列满产生丢包,其中一个做法就是加大半/全连接队列的长度。 半连接队列长度Linux内核中,主要受tcp_max_syn_backlog影响 加大它到一个合适的值就可以。

# cat /proc/sys/net/ipv4/tcp_max_syn_backlog

1024

# echo "2048" > /proc/sys/net/ipv4/tcp_max_syn_backlog

全连接队列长度是应用程序调用listen时传入的backlog以及内核参数net.core.somaxconn二者之中较小的那个。你可能需要同时调整你的应用程序和该内核参数。

# cat /proc/sys/net/core/somaxconn

128

# echo "256" > /proc/sys/net/core/somaxconn

改完之后我们可以通过ss命令输出的Send-Q确认最终生效长度:

$ ss -nlt

Recv-Q Send-Q Local Address:Port Address:Port

0      128    *:80               *:*

Recv-Q告诉了我们当前该进程的全连接队列使用长度情况。如果Recv-Q已经逼近了Send-Q,那么可能不需要等到丢包也应该准备加大你的全连接队列了。

如果加大队列后仍然有非常偶发的队列溢出的话,我们可以暂且容忍。

如果仍然有较长时间处理不过来怎么办?

另外一个做法就是直接报错,不要让客户端超时等待。

例如将Redis、Mysql等后端接口的内核参数tcp_abort_on_overflow为1。如果队列满了,直接发reset给client。告诉后端进程/线程不要痴情地傻等。这时候client会收到错误“connection reset by peer”。牺牲一个用户的访问请求,要比把整个站都搞崩了还是要强的。

5、TCP连接耗时实测分析

5.1 测试前的准备

我写了一段非常简单的代码,用来在客户端统计每创建一个TCP连接需要消耗多长时间。

<?php

$ip= {服务器ip};

$port= {服务器端口};

$count= 50000;

function buildConnect($ip,$port,$num){

for($i=0;$i<$num;$i++){

$socket= socket_create(AF_INET,SOCK_STREAM,SOL_TCP);

if($socket==false) {

echo"$ip $port socket_create() 失败的原因是:".socket_strerror(socket_last_error($socket))."\n";

sleep(5);

continue;

}

if(false == socket_connect($socket, $ip, $port)){

echo"$ip $port socket_connect() 失败的原因是:".socket_strerror(socket_last_error($socket))."\n";

sleep(5);

continue;

}

socket_close($socket);

}

}

$t1= microtime(true);

buildConnect($ip, $port, $count);

echo(($t2-$t1)*1000).'ms';

在测试之前,我们需要本机linux可用的端口数充足,如果不够50000个,最好调整充足。

# echo "5000   65000" /proc/sys/net/ipv4/ip_local_port_range

5.2 正常情况下的测试

注意:无论是客户端还是服务器端都不要选择有线上服务在跑的机器,否则你的测试可能会影响正常用户访问

首先:我的客户端位于河北怀来的IDC机房内,服务器选择的是公司广东机房的某台机器。执行ping命令得到的延迟大约是37ms,使用上述脚本建立50000次连接后,得到的连接平均耗时也是37ms。

这是因为前面我们说过的,对于客户端来看,第三次的握手只要包发送出去,就认为是握手成功了,所以只需要一次RTT、两次传输耗时。虽然这中间还会有客户端和服务端的系统调用开销、软中断开销,但由于它们的开销正常情况下只有几个us(微秒),所以对总的连接建立延时影响不大。

接下来:我换了一台目标服务器,该服务器所在机房位于北京。离怀来有一些距离,但是和广东比起来可要近多了。这一次ping出来的RTT是1.6~1.7ms左右,在客户端统计建立50000次连接后算出每条连接耗时是1.64ms。

再做一次实验:这次选中实验的服务器和客户端直接位于同一个机房内,ping延迟在0.2ms~0.3ms左右。跑了以上脚本以后,实验结果是50000 TCP连接总共消耗了11605ms,平均每次需要0.23ms。

线上架构提示:这里看到同机房延迟只有零点几ms,但是跨个距离不远的机房,光TCP握手耗时就涨了4倍。如果再要是跨地区到广东,那就是百倍的耗时差距了。线上部署时,理想的方案是将自己服务依赖的各种mysql、redis等服务和自己部署在同一个地区、同一个机房(再变态一点,甚至可以是甚至是同一个机架)。因为这样包括TCP链接建立啥的各种网络包传输都要快很多。要尽可能避免长途跨地区机房的调用情况出现。

5.3 TCP连接队列溢出情况下的测试

测试完了跨地区、跨机房和跨机器。这次为了快,直接和本机建立连接结果会咋样呢?

Ping本机ip或127.0.0.1的延迟大概是0.02ms,本机ip比其它机器RTT肯定要短。我觉得肯定连接会非常快,嗯实验一下。

连续建立5W TCP连接:总时间消耗27154ms,平均每次需要0.54ms左右。

嗯!?怎么比跨机器还长很多?

有了前面的理论基础,我们应该想到了:由于本机RTT太短,所以瞬间连接建立请求量很大,就会导致全连接队列或者半连接队列被打满的情况。一旦发生队列满,当时撞上的那个连接请求就得需要3秒+的连接建立延时。所以上面的实验结果中,平均耗时看起来比RTT高很多。

在实验的过程中,我使用tcpdump抓包看到了下面的一幕。原来有少部分握手耗时3s+,原因是半连接队列满了导致客户端等待超时后进行了SYN的重传。

我们又重新改成每500个连接,sleep 1秒。嗯好,终于没有卡的了(或者也可以加大连接队列长度)。

结论是:本机50000次TCP连接在客户端统计总耗时102399 ms,减去sleep的100秒后,平均每个TCP连接消耗0.048ms。比ping延迟略高一些。

这是因为当RTT变的足够小的时候,内核CPU耗时开销就会显现出来了,另外TCP连接要比ping的icmp协议更复杂一些,所以比ping延迟略高0.02ms左右比较正常。

6、本文小结

TCP连接在建立异常的情况下,可能需要好几秒,一个坏处就是会影响用户体验,甚至导致当前用户访问超时都有可能。另外一个坏处是可能会诱发雪崩。

所以当你的服务器使用短连接的方式访问数据的时候:一定要学会要监控你的服务器的连接建立是否有异常状态发生。如果有,学会优化掉它。当然你也可以采用本机内存缓存,或者使用连接池来保持长连接,通过这两种方式直接避免掉TCP握手挥手的各种开销也可以。

再说正常情况下:TCP建立的延时大约就是两台机器之间的一个RTT耗时,这是避免不了的。但是你可以控制两台机器之间的物理距离来降低这个RTT,比如把你要访问的redis尽可能地部署的离后端接口机器近一点,这样RTT也能从几十ms削减到最低可能零点几ms。

最后我们再思考一下:如果我们把服务器部署在北京,给纽约的用户访问可行吗?

前面的我们同机房也好,跨机房也好,电信号传输的耗时基本可以忽略(因为物理距离很近),网络延迟基本上是转发设备占用的耗时。但是如果是跨越了半个地球的话,电信号的传输耗时我们可得算一算了。 北京到纽约的球面距离大概是15000公里,那么抛开设备转发延迟,仅仅光速传播一个来回(RTT是Rround trip time,要跑两次),需要时间 = 15,000,000 *2 / 光速 = 100ms。实际的延迟可能比这个还要大一些,一般都得200ms以上。建立在这个延迟上,要想提供用户能访问的秒级服务就很困难了。所以对于海外用户,最好都要在当地建机房或者购买海外的服务器。

附录:更多网络编程精华资料

[1] 网络编程(基础)资料:

  1. TCP/IP详解 - 第17章·TCP:传输控制协议
  2. 技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)
  3. 通俗易懂-深入理解TCP协议(上):理论基础
  4. 理论经典:TCP协议的3次握手与4次挥手过程详解
  5. P2P技术详解(一):NAT详解——详细原理、P2P简介
  6. 网络编程懒人入门(一):快速理解网络通信协议(上篇)
  7. 网络编程懒人入门(二):快速理解网络通信协议(下篇)
  8. 网络编程懒人入门(三):快速理解TCP协议一篇就够
  9. 网络编程懒人入门(四):快速理解TCP和UDP的差异
  10. 网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势
  11. 网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门
  12. 网络编程懒人入门(七):深入浅出,全面理解HTTP协议
  13. 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接
  14. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?
  15. 网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议
  16. 网络编程懒人入门(十一):一文读懂什么是IPv6
  17. 网络编程懒人入门(十二):快速读懂Http/3协议,一篇就够!
  18. 网络编程懒人入门(十三):一泡尿的时间,快速搞懂TCP和UDP的区别
  19. 网络编程懒人入门(十四):到底什么是Socket?一文即懂!
  20. 技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解
  21. 让互联网更快:新一代QUIC协议在腾讯的技术实践分享
  22. 聊聊iOS中网络编程长连接的那些事
  23. IPv6技术详解:基本概念、应用现状、技术实践(上篇)
  24. IPv6技术详解:基本概念、应用现状、技术实践(下篇)
  25. Java对IPv6的支持详解:支持情况、相关API、演示代码
  26. 从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路
  27. 脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手
  28. 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
  29. 脑残式网络编程入门(三):HTTP协议必知必会的一些知识
  30. 脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)
  31. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?
  32. 脑残式网络编程入门(六):什么是公网IP和内网IP?NAT转换又是什么鬼?
  33. 脑残式网络编程入门(七):面视必备,史上最通俗计算机网络分层详解
  34. 脑残式网络编程入门(八):你真的了解127.0.0.1和0.0.0.0的区别?
  35. 脑残式网络编程入门(九):面试必考,史上最通俗大小端字节序详解
  36. 迈向高阶:优秀Android程序员必知必会的网络基础
  37. Android程序员必知必会的网络通信传输层协议——UDP和TCP
  38. 技术大牛陈硕的分享:由浅入深,网络编程学习经验干货总结
  39. 可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?
  40. 5G时代已经到来,TCP/IP老矣,尚能饭否?
  41. >> 更多同类文章 ……

[2] 网络编程(高阶)资料:

  1. 高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少
  2. 高性能网络编程(二):上一个10年,著名的C10K并发连接问题
  3. 高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了
  4. 高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索
  5. 高性能网络编程(五):一文读懂高性能网络编程中的I/O模型
  6. 高性能网络编程(六):一文读懂高性能网络编程中的线程模型
  7. 高性能网络编程(七):到底什么是高并发?一文即懂!
  8. IM开发者的零基础通信技术入门(十):零基础,史上最强5G技术扫盲
  9. IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!
  10. IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!
  11. IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!
  12. IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!
  13. IM开发者的零基础通信技术入门(十五):理解定位技术,一篇就够
  14. 以网游服务端的网络接入层设计为例,理解实时通信的技术挑战
  15. 知乎技术分享:知乎千万级并发的高性能长连接网关技术实践
  16. 淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路
  17. >> 更多同类文章 ……

(本文已同步发布于:http://www.52im.net/thread-3265-1-1.html

不为人知的网络编程(十一):从底层入手,深度分析TCP连接耗时的秘密的更多相关文章

  1. 不为人知的网络编程(八):从数据传输层深度解密HTTP

    1.引言 在文章<理论联系实际:Wireshark抓包分析TCP 3次握手.4次挥手过程>中,我们学会了用wireshark来分析TCP的“三次握手,四次挥手”,非常好用.这就是传说中的锤 ...

  2. 不为人知的网络编程(九):理论联系实际,全方位深入理解DNS

    本文原作者:selfboot,博客地址:selfboot.cn,Github地址:github.com/selfboot,感谢原作者的技术分享. 1.引言 对于 DNS(Domain Name Sys ...

  3. java网络编程--2 IP,端口,通信协议,TCP/UDP对比

    java网络编程--2 IP,端口,通信协议,TCP/UDP对比 1.3.IP ip地址:InetAddress 唯一定位一台网络上的计算机 127.0.0.1 :本机localhost IP地址的分 ...

  4. 网络编程基础之C/S架构和TCP/IP协议

    一.何谓C/S架构 C指的是client(客户端软件),S指的是Server(服务端软件),既然我们的的标题是网络编程基础, 那我们就一起来学习怎样写一个C/S架构的软件,实现服务端与客户端软件基于网 ...

  5. 网络编程学习笔记(二)基于TCP的Socket编程

    1.Socket:英文意思插座.两个Java应用程序可以通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket. 2.Socket通常用来实现client-server(客户端 ...

  6. Qt网络编程-书接上文,浅谈TCP文件收发,以及心跳包

    qt网络编程-书接上文,浅谈文件收发 上文Qt网络编程-从0到多线程编程中谈到 在qt中的qtcpsocket通讯的用法,接下来浅谈一下关于tcp通讯的实际应用,当然了由于是浅谈,也不能保证其功能的完 ...

  7. iOS网络编程笔记——Socket底层实现笔记

    Socket简单底层实现笔记: 以Socket客户端编程为例: 1.导入头文件 #import <arpa/inet.h> #import <netinet/in.h> #im ...

  8. ACE网络编程:IPC SAP、ACE_SOCKET和TCP/IP通信实例

    socket.TLI.STREAM管道和FIFO为访问局部和全局IPC机制提供广泛的接口.但是,有许多问题与这些不统一的接口有关联.比如类型安全的缺乏和多维度的复杂性会导致成问题的和易错的编程.ACE ...

  9. UNIX网络编程卷1 时间获取程序server TCP 协议相关性

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码:  这是一个简单的时间获取server程序.它和时间获取程序client一道工作. ...

  10. linux网络编程(socket)之面向连接(TCP/IP)

    1.流程 服务器: 创建socket: 绑定端口: 监听: 监听到有连接请求,接受请求: 建立连接,开始对话. 客户端: 创建socket: 请求建立连接: 连接建立成功,开始对话. 2.实例代码 / ...

随机推荐

  1. 云原生周刊:Kubernetes v1.27 发布 | 2023.4.17

    开源项目推荐 Palaemon Palaemon 是一个开源开发工具,用于监控 Kubernetes 集群的健康状况和资源指标并分析内存不足 (OOMKill) 错误. Gitkube Gitkube ...

  2. synchronized锁的内容

    synchronized锁的内容 import java.util.concurrent.TimeUnit; class Test1 { public static void main(String[ ...

  3. 多元/多维高斯/正态分布概率密度函数推导 (Derivation of the Multivariate/Multidimensional Normal/Gaussian Density)

    各种维度正态分布公式: 一维正态分布 二维正态分布/多维正态分布 各向同性正态分布 注:即方差都是一样的,均值不一样,方差的值可以单独用标量表示. 多元/多维高斯/正态分布概率密度函数推导 (Deri ...

  4. 哈希(C语言)

    文章目录 1.数据结构--哈希表 1.1哈希表的工作原理 1.2哈希表的代码实现 2.哈希算法 2.1 哈希算法介绍 2.2C语言实现示例 本文介绍一个常用的算法--哈希算法,哈希算法依赖于哈希表来实 ...

  5. 每日学学Java开发规范,编程规约(附阿里巴巴Java开发手册(终极版))

    前言 每次去不同的公司,码不同的代码,适应不同的规范,经常被老大教育规范问题,我都有点走火入魔的感觉,还是要去看看阿里巴巴Java开发规范,从中熟悉一下,纠正自己,码出高效,码出质量. 想细看的可以去 ...

  6. Avalonia跨平台上位机控件开发之水泵

    Avalonia跨平台上位机控件开发之水泵 随着国产化的推进,越来越多的开发者选择使用跨平台的框架来创建上位机应用,而Avalonia正是一个优秀的选择.本文将探讨如何利用Avalonia框架进行水泵 ...

  7. HAL+CubeIDE,STM32F407ZGT6正点原子探索者,舵机驱动,从零开始

    CubeIDE_HAL库_从零开始玩舵机 1.材料准备 开发板:正点原子STM32F407ZGT6探索者 舵机:SG90 舵机线材分辨:褐色 / 红色 / 橘黄色 -- GND / VCC / PWM ...

  8. 题解:CF1776L Controllers

    CF1776L Controllers 题解 分析 先把题目形式化.设 \(n\) 次加减中有 \(x\) 个加,\(y\) 个减,其中 \(a\) 加了 \(u\) 次,减了 \(v\) 次,显然 ...

  9. P3920 WC2014 紫荆花之恋

    P3920 WC2014 紫荆花之恋 毒瘤题目,动态点分树. 前置科技点 替罪羊树 高速平衡树(除去 fhq_treap 和 splay 之外的所有平衡树) 约定 \(dis(u,v)\) 为原树上 ...

  10. 2024 BUPT Programming Contest F

    简要题意 多测,给定一个 \(n \times n\) 矩阵,矩阵中的每一个元素的计算方式如下: 矩阵的行和列唯一决定两个整数对 \((a, b)\),矩阵第 \(a(0 \le a < n)\ ...