基础知识

来源:互联网 发布:淘宝申请介入流程 编辑:程序博客网 时间:2024/05/29 07:50

1、C语言结构体所占用的字节数如何计算
格式一:  

01.struct tagPhone02.{03.     char   A;04.     int    B;05.     short  C;06.}Phone;

  格式二:

01.struct tagPhone02.{03.     char   A;04.     short  C;05.     int    B;06.}Phone2;

  格式三:

01.struct tagPhone302.{03.     char   A;04.     char   B[2];05.     char   C[4];06.}Phone3;

我们都知道,char类型占用1个字节,int型占用4个字节,short类型占用2个字节,long占用8个,double占用16个;
  那么我们可能会犯一个错误就是直接1+4+2=7,该结构体占用7个字节。这是错的。
  以下我们简单分析下:
  计算结构体大小时需要考虑其内存布局,结构体在内存中存放是按单元存放的,每个单元多大取决于结构体中最大基本类型的大小。
  对格式一:  
    
  以int型占用4个来作为倍数,因为A占用一个字节后,B放不下,所以开辟新的单元,然后开辟新的单元放C,所以格式一占用的字节数为:3*4=12;
  同理对于格式二
    
  A后面还有三个字节,足够C存放,所以C根着A后面存放,然后开辟新单元存放B数据。所以格式二占用的内存字节为2*4=8.  
  对于格式三:
  
  上面结构计算大小,sizeof(Phone3) = 1 + 2 + 4 = 7, 其大小为结构体中个字段大小之和,这也是最节省空间的一种写法。
  总结:
  第一种写法,空间浪费严重,sizeof 计算大小与预期不一致,但是保持了每个字段的数据类型。这也是最常见的漫不经心的写法,一般人很容易这样写;
  第三种写法,最节省空间的写法,也是使用 sizeof 求大小与预期一样的写法,但是全部使用字节类型,丢失了字段本生的数据类型,不方便使用;

  第二种写法,介于第一种和第三种写法之间,其空间上比较紧凑,同时又保持了结构体中字段的数据类型。

2、面向对象设计的三个基本要素与五个基本设计原则
面向对象的三个基本特征是:封装、继承、多态。
面向对象设计的五个基本设计原则是:单一职责原则(SRP)、开放封闭原则(OCP)、Liskov替换原则(LSP)、依赖倒置原则(DIP)、接口隔离原则(ISP)

3、TCP连接
面试时看到应聘者简历中写精通网络,TCP编程,我常问一个问题,TCP建立连接需要几次握手?95%以上的应聘者都能答对是3次。问TCP断开连接需要几次握手,70%的应聘者能答对是4次通讯。再问CLOSE_WAIT,TIME_WAIT是什么状态,怎么产生的,对服务有什么影响,如何消除?有一部分同学就回答不上来。不是我扣细节,而是在通讯为主的前端服务器上,必须有能力处理各种TCP状态。比如统计在本厂的一台前端机上高峰时间TCP连接的情况,统计命令:

Linux shell代码 收藏代码

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'  

结果:

除了ESTABLISHED,可以看到连接数比较多的几个状态是:FIN_WAIT1, TIME_WAIT, CLOSE_WAIT, SYN_RECV和LAST_ACK;下面的文章就这几个状态的产生条件、对系统的影响以及处理方式进行简单描述。

  • TCP状态

TCP状态如下图所示:

可能有点眼花缭乱?再看看这个时序图

下面看下大家一般比较关心的三种TCP状态
SYN_RECV

服务端收到建立连接的SYN没有收到ACK包的时候处在SYN_RECV状态。有两个相关系统配置:

1,net.ipv4.tcp_synack_retries :INTEGER

默认值是5

对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。通常我们不对这个值进行修改,因为我们希望TCP连接不要因为偶尔的丢包而无法建立。
2,net.ipv4.tcp_syncookies

一般服务器都会设置net.ipv4.tcp_syncookies=1来防止SYN Flood攻击。假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟)。

这些处在SYNC_RECV的TCP连接称为半连接,并存储在内核的半连接队列中,在内核收到对端发送的ack包时会查找半连接队列,并将符合的requst_sock信息存储到完成三次握手的连接的队列中,然后删除此半连接。大量SYNC_RECV的TCP连接会导致半连接队列溢出,这样后续的连接建立请求会被内核直接丢弃,这就是SYN Flood攻击。

能够有效防范SYN Flood攻击的手段之一,就是SYN Cookie。SYN Cookie原理由D. J. Bernstain和 Eric Schenk发明。SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。

观测服务上SYN_RECV连接个数为:7314,对于一个高并发连接的通讯服务器,这个数字比较正常。
CLOSE_WAIT

发起TCP连接关闭的一方称为client,被动关闭的一方称为server。被动关闭的server收到FIN后,但未发出ACK的TCP状态是CLOSE_WAIT。出现这种状况一般都是由于server端代码的问题,如果你的服务器上出现大量CLOSE_WAIT,应该要考虑检查代码。
TIME_WAIT

根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方 socket将进入TIME_WAIT状态。TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),在Windows下默认为4分钟,即240秒。TIME_WAIT状态下的socket不能被回收使用. 具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务。

为什么需要TIME_WAIT?TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是必要的逻辑保证。

和TIME_WAIT状态有关的系统参数有一般由3个,本厂设置如下:

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_fin_timeout,默认60s,减小fin_timeout,减少TIME_WAIT连接数量。

net.ipv4.tcp_tw_reuse = 1表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。

4、iOS后缀名文件
h :头文件。头文件包含类,类型,函数和常数的声明。
.m :源代码文件。这是典型的源代码文件扩展名,可以包含Objective-C和C代码。
.mm :源代码文件。带有这种扩展名的源代码文件,除了可以包含Objective-C和C代码以外还可以包含C++代码。仅在你的Objective-C代码中确实需要使用C++类或者特性的时候才用这种扩展名(百度地图第三方就用到了)
.cpp:只能编译C++
当你需要在源代码中包含头文件的时候,你可以使用标准的#include编译选项,但是Objective-C提供了更好的方法。#import选项和#include选项完全相同,只是它可以确保相同的文件只会被包含一次。Objective-C的例子和文档都倾向于使用#import。
.m 和.mm 的区别是告诉gcc 在编译时要加的一些参数。当然.mm还可以命名成.m,但在编译时要手动加参数(麻烦)

5、TCP/IP协议
从地址栏里输入网址,回车直到页面打开。按照TCP/IP协议,从应用层到链路层经过哪些协议?他们的作用?
应用层(Application):
HTTP超文本传输协议,提供www等服务。输入的网址包含http://,一般为默认。
DNS动态域名系统,提供域名到IP地址的解析
FTP文件传输协议,提供文件的传送,如上传,下载
RIP路由信息协议,提供路由信息
传输层(Transport):
TCP传输控制协议,提供面向连接的,端到端的,可靠的数据传输
UDP用户数据报协议,提供面向无连接的,不可靠的,快捷的数据传输
网际层(Internet):
IP因特网通信协议,负责选择数据传送的道路。主要有两个功能:寻址,分段。
ARP地址解析协议,提供IP地址到MAC地址的解析
ICMP控制报文协议,提供IP主机,路由器之间控制消息(网络通不通)的传递。
链路层(link):
PPP点对点协议,提供路由器之间或者主机之间的连接
6、Android ANR
ANR定义:在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。所以一个流畅的合理的应用程序中不能出现anr,而让用户每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。

默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒。

第一:什么会引发ANR?

在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:

1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
2.BroadcastReceiver在10秒内没有执行完毕

造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。

潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。

第二:如何避免ANR?

1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等)

2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver,关于原因后续会有介绍,此处不是本文重点)

3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。

总结:anr异常也是在程序中自己经常遇到的问题,主要的解决办法自己最常用的就是不要在主线程中做耗时的操作,而应放在子线程中来实现,比如采用Handler+mesage的方式,或者是有时候需要做一些和网络相互交互的耗时操作就采用asyntask异步任务的方式(它的底层其实Handler+mesage有所区别的是它是线程池)等,在主线程中更新UI。

7、Android dip

度量单位含义

  dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。  dp: dip是一样的 px: pixels(像素). 不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多。 pt: point,是一个标准的长度单位,1pt=1/72英寸,用于印刷业,非常简单易用; sp: scaled pixels(放大像素). 主要用于字体显示best for textsize。in(英寸):长度单位。 mm(毫米):长度单位。dip(value)=(int) (px(value)/1.5 + 0.5) 
0 0