查看队列深度_不为人知的网络编程(十一):从底层入手,深度分析TCP连接耗时的秘密...

“ 本文作者张彦飞,原题“聊聊TCP连接耗时的那些事儿”,本次收录已征得作者同意,转载请联系作者。即时通讯网收录时有少许改动。本文已同步发布于52im社区:http://www.52im.net/thread-3265-1-1.html(

1、引言

对于基于互联网的通信应用(包括IM聊天、推送系统在内),数据传递时使用TCP协议相对较多。这是因为在TCP/IP协议簇的传输层协议中,TCP协议具备可靠的连接、错误重传、拥塞控制等优点,所以目前在应用场景上比UDP更广泛一些。相信你也一定听闻过TCP也存在一些缺点,能常都是老生常谈的开销要略大。但是各路技术博客里都在单单说开销大、或者开销小,而少见不给出具体的量化分析。不客气的讲,类似论述都是没什么营养的废话。经过日常工作的思考之后,我更想弄明白的是,TCP的开销到底有多大,能否进行量化。一条TCP连接的建立需要耗时延迟多少,是多少毫秒,还是多少微秒?能不能有一个哪怕是粗略的量化估计?当然影响TCP耗时的因素有很多,比如网络丢包等等。我今天只分享我在工作实践中遇到的比较高发的各种情况。写在前面:得益于Linux内核的开源,本文中所提及的底层以及具体的内核级代码例子,都是以Linux系统为例。本文已同步发布于“即时通讯技术圈”公众号,欢迎关注。公众号上的链接是:点此进入。

2、系列文章

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

  • 《不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)》

  • 《不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)》

  • 《不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT》

  • 《不为人知的网络编程(四):深入研究分析TCP的异常关闭》

  • 《不为人知的网络编程(五):UDP的连接性和负载均衡》

  • 《不为人知的网络编程(六):深入地理解UDP协议并用好它》

  • 《不为人知的网络编程(七):如何让不可靠的UDP变的可靠?》

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

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

  • 《不为人知的网络编程(十):深入操作系统,从内核理解网络包的接收过程(Linux篇)》

  • 《不为人知的网络编程(十一):从底层入手,深度分析TCP连接耗时的秘密》(本文)

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

要想搞清楚TCP连接的耗时,我们需要详细了解连接的建立过程。在前文《深入操作系统,从内核理解网络包的接收过程(Linux篇)》中我们介绍了数据包在接收端是怎么被接收的:数据包从发送方出来,经过网络到达接收方的网卡;在接收方网卡将数据包DMA到RingBuffer后,内核经过硬中断、软中断等机制来处理(如果发送的是用户数据的话,最后会发送到socket的接收队列中,并唤醒用户进程)。58c476cd40080ead16cebb8c446bb318.png在软中断中,当一个包被内核从RingBuffer中摘下来的时候,在内核中是用struct sk_buff结构体来表示的(参见内核代码include/linux/skbuff.h)。其中的data成员是接收到的数据,在协议栈逐层被处理的时候,通过修改指针指向data的不同位置,来找到每一层协议关心的数据。704d436c79a5948bce2a179451594ed5.png对于TCP协议包来说,它的Header中有一个重要的字段-flags。如下图:7e42b3ccff3898a232447c7aa17abcfc.png通过设置不同的标记侠,将TCP包分成SYNC、FIN、ACK、RST等类型:

  • 1)客户端通过connect系统调用命令内核发出SYNC、ACK等包来实现和服务器TCP连接的建立;

  • 2)在服务器端,可能会接收许许多多的连接请求,内核还需要借助一些辅助数据结构-半连接队列和全连接队列。

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

  • 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不够用了,需要扩容。当时的服务器监控如下图:ad4a0e29a02fe3eb92d5f998b0ab5bf1.png该服务之前一直每秒抗2000左右的qps,CPU的idel一直有70%+,怎么突然就CPU一下就不够用了呢。而且更奇怪的是CPU被打到谷底的那一段时间,负载却并不高(服务器为4核机器,负载3-4是比较正常的)。后来经过排查以后发现当TCP客户端TIME_WAIT有30000左右,导致可用端口不是特别充足的时候,connect系统调用的CPU开销直接上涨了100多倍,每次耗时达到了2500us(微秒),达到了毫秒级别。e237be772d9aa332c451d69b39edaf5e.png09b2319ce9a9313cc1804d06805940df.png当遇到这种问题的时候,虽然TCP连接建立耗时只增加了2ms左右,整体TCP连接耗时看起来还可接受。但这里的问题在于这2ms多都是在消耗CPU的周期,所以问题不小。解决起来也非常简单,办法很多:修改内核参数net.ipv4.ip_local_port_range多预留一些端口号、改用长连接都可以。

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

如果连接建立的过程中,任意一个队列满了,那么客户端发送过来的syn或者ack就会被丢弃。客户端等待很长一段时间无果后,然后会发出TCP Retransmission重传。拿半连接队列举例:5846e52f4b6dfb4b93c67cf1f9c1a933.png要知道的是上面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 times the listen queue of a socket overflowed

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

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

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

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

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

$ ss -nltRecv-Q Send-Q Local Address:Port Address:Port0      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.3TCP连接队列溢出情况下的测试

测试完了跨地区、跨机房和跨机器。这次为了快,直接和本机建立连接结果会咋样呢?Ping本机ip或127.0.0.1的延迟大概是0.02ms,本机ip比其它机器RTT肯定要短。我觉得肯定连接会非常快,嗯实验一下。连续建立5W TCP连接:总时间消耗27154ms,平均每次需要0.54ms左右。嗯!?怎么比跨机器还长很多?有了前面的理论基础,我们应该想到了:由于本机RTT太短,所以瞬间连接建立请求量很大,就会导致全连接队列或者半连接队列被打满的情况。一旦发生队列满,当时撞上的那个连接请求就得需要3秒+的连接建立延时。所以上面的实验结果中,平均耗时看起来比RTT高很多。在实验的过程中,我使用tcpdump抓包看到了下面的一幕。原来有少部分握手耗时3s+,原因是半连接队列满了导致客户端等待超时后进行了SYN的重传。eac9709cd49891fbf5e60d0280437433.png我们又重新改成每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以上。建立在这个延迟上,要想提供用户能访问的秒级服务就很困难了。所以对于海外用户,最好都要在当地建机房或者购买海外的服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567203.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

几级工作台做石头高墙_创造与魔法:建筑新手入门攻略,家园建材怎么做

hello大家好&#xff0c;又见面啦&#xff0c;我是创造与魔法郁金香建筑团的建筑师&#xff0c;九梨梨众所周知&#xff0c;我是一个热衷于出各类建筑案例的人&#xff0c;玩创魔两年多&#xff0c;做了好几十个不同款式的家园吧。其实创魔这个游戏&#xff0c;建筑只是其中一个…

oracle vitu,Supply Chain Management (SCM) a Manufacturing | Oracle Česká Republika

Nebyly nalezeny ždn vsledkyVašemu vyhledvn neodpovdaj ždn vsledky.Abyste našli to, co hledte, doporučujeme vyzkoušet nsledujc postup:Zkontrolujte pravopis vašich klčovch slov ve vyhledvn.Použijte synonyma pro klčov slovo, kter jste zadali, napřk…

两步路轨迹文件位置_最新Uber ATG的轨迹预测方法LiRaNet介绍

arXiv今年10月刚刚上传论文“LiRaNet: End-to-End Trajectory Prediction using Spatio-Temporal Radar Fusion“。其特色在于&#xff0c;除了激光雷达和HD Map之外&#xff0c;该轨迹预测方法采用了雷达传感器的信息。雷达和激光雷达融合是有挑战性的&#xff0c;因为前者的低…

linux查看目录下 开头,Linux下ls如何看到.开头的文件

Linux下ls查看到.开头的文件方法&#xff1a;ls -aLinux操作系统是UNIX操作系统的一种克隆系统&#xff0c;它诞生于1991 年的10 月5 日(这是第一次正式向外公布的时间)。以后借助于Internet网络&#xff0c;并通过全世界各地计算机爱好者的共同努力&#xff0c;已成为今天世界…

增值电信服务费是什么意思_增值电信业务IDC许可证要年检吗,流程是什么

据国家相关法律法规&#xff0c;持有IDC许可证的企业每年年初都需要办理IDC年检&#xff0c;企业也应当重视IDC年检&#xff0c;否则将会面临惩罚&#xff0c;所以小编来给大家介绍云南IDC许可证年检流程。为什么要办理云南IDC许可证年检,如何办理?根据《中华人民共和国电信条…

linux查看进程调用接口,查看某个程序都调用哪些api函数

查看某个程序都调用哪些api函数以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;查看某个程序都调用哪些api函数vs6里带了个工具叫depends可以看反汇编软件w32dasm也可以希望能帮到你windows编…

linux生产上线工具,Linux 产能工具及其使用技巧

由于生产力本身是一个主观术语&#xff0c;我不打算详细解释我这里要讲到的“生产力”是什么。我打算给你们展示一些工具及其使用技巧&#xff0c;希望这会帮助你在Linux中工作时能更专注、更高效&#xff0c;并且能节省时间。Linux产能工具及其使用技巧再次说明&#xff0c;我…

现代汉语词典第五版_从现代汉语词典“哀兵必胜”词条说起

本文属本公众号原创。想转发可以后台留言&#xff0c;别洗我们的稿&#xff01;最近&#xff0c;编校一姐一直在研读《现代汉语词典》(第7版)&#xff0c;将会陆续发布学习心得。今天&#xff0c;说一说“哀兵必胜”词条。第一版第五版第六版第七版故抗兵相若(加)&#xff0c;(…

linux通讯录软件带头像,小程序新技能 Get!保存微信好友头像到手机通讯录

原标题&#xff1a;小程序新技能 Get&#xff01;保存微信好友头像到手机通讯录亲爱的朋友&#xff0c;你知道来电时能看到好友的头像是一种怎样的体验吗&#xff1f;你是否注意过这样一件事&#xff1a;每当打开自己的微博、微信等社交软件&#xff0c;除了扑面而来的信息流之…

linux vmware硬盘,给vmware的Linux虚拟机增添硬盘

给vmware的Linux虚拟机添加硬盘1、先将虚拟机Power Off&#xff0c;在Virtual Machine Setting对话框里点击左下角的“Add”&#xff0c;选择“Hard Disk”&#xff0c;之后选择“Create a new virtual disk”&#xff0c;分配容量&#xff0c;其他默认配置就可以了。2、启动虚…

linux常用调试,linux下gdb常用的调试命令

用gdb调试程序时&#xff0c;常常很困惑一些命令的使用&#xff0c;要么是不知道这个命令&#xff0c;要么忘了命令的使用方法。接下来是小编为大家收集的linux下gdb常用的调试命令&#xff0c;希望能帮到大家。linux下gdb常用的调试命令gdb常用&#xff1a;run 启动程序运行ne…

linux vg备份还原,Oracle Linux 6.4 误删VG之恢复过程

五、VG恢复思路1、在/etc/lvm/存放着LVM的配置、归档、备份等信息。[rootol64 ~]# ls -l /etc/lvmtotal 52drwx------. 2 root root 4096 Nov 18 08:30 archivedrwx------. 2 root root 4096 Nov 18 08:30 backupdrwx------. 2 root root 4096 Feb 24 2013 cache-rw-r--r--. 1 …

linux cat cd,linux 文件系统命令 cat cd chmod

cd&#xff0c;有时也写作chdir(change directory&#xff0c;改变目录)&#xff0c;是在Unix、Windows和DOS操作系统下用于改变工作目录的命令行命令。在Unix的外壳脚本与Windows或DOS的批处理文件中亦可使用。CHDIR()还是Visual Basic改变工作目录的一个函数。目录是文件系统…

数据结构c语言版编程软件,数据结构严蔚敏4版PDF下载_数据结构C语言版严蔚敏下载 完整版_当载软件站...

数据结构C语言版严蔚敏 是《data structures and algorithm analysis in c》一书第2版的简体中译本。原书曾被评为20世纪顶尖的30部计算机著作之一&#xff0c;作者mark allen weiss在数据结构和算法分析方面卓有建树&#xff0c;他的数据结构和算法分析的著作尤其畅销&#xf…

android网络盒子改,有什么办法可以把淘汰下来的安卓手机改造成电视盒子用?...

基本上谁家都会有一两部旧的手机&#xff0c;其实并不是不能用或者坏了&#xff0c;只是配置有些低。我们只需要简单改造一下&#xff0c;就可以将旧手机改造成电视盒子&#xff0c;而且比普通的网络盒子性能更强大。有线方式我们需要准备一根MHL线&#xff0c;大部分的安卓手机…

android palette组件用法,Android Support Palette使用详解

使用Palette API选择颜色良好的视觉设计是app成功所必不可少的, 而色彩设计体系是设计的基础构成. Palette包是支持包, 能够从图片中解析出突出的颜色, 从而帮助你创建出视觉迷人的应用你能够使用Palette包设计布局主题, 并把自定义色彩应用到可视化元素中. 比如, 你可以根据专…

android ui stencil kit 下载,实用的iOS6/iPhone5 GUI/iPad PSD以及其它版本素材

实用的iOS6/iPhone5 GUI/iPad PSD以及其它版本素材10月 16, 2012评论 (1)Sponsor现在使用Apple旗下产品越来越多&#xff0c;比如iPhoneiPad等&#xff0c;正因如此&#xff0c;我们需要设计这类的apps应用也相对多了&#xff0c;所以如果有一些现用素材的话可以帮助设计师快速…

android下拉弹性gif,android-pulltorefresh 下拉加载中使用gif动图

效果预览&#xff1a;xml布局xmlns:ptr"http://schemas.android.com/apk/res-auto"android:layout_width"fill_parent"android:layout_height"fill_parent"android:divider"#00000000"android:cacheColorHint"#00000000"and…

unity3d android aar,Android Stuido导出AAR 给Unity3D调用注意事项

1. 导出 AAR过程需要注意&#xff0c;依赖的文件并没有打进去&#xff0c;所以要收到拷入到 Unity项目中&#xff0c;如下图中的 support包&#xff0c;是我项目中要用到的&#xff1a;2.删除aar包中重复的 libs下的 jar文件和 jni下的 .so文件&#xff0c;否则调用的时候会报…

html中图片响应式怎么写,如何使用 HTML5 的picture元素处理响应式图片

图片在响应式网页设计中是出了名的最具挑战性的方面之一。今天我们就来看看如何使用元素来处理响应式图片.让我们先了解一下问题固定宽度&#xff0c;像素完美的网站设计已经离我们远去了。在宽屏显示器&#xff0c;互联网电视&#xff0c;多尺寸的平板电脑和智能手机的今天&am…