注:很多内容来源于网络,各种收集而来,所以已标识为转载。
一、Http协议
1、支持C/S模式
2、简单快速,协议简单,通讯速度快,通常有的请求方法GET、HEAD、POST
3、灵活,可以传输任意类型的对象,Content-Type
4、无连接,请求处理完后断开连接
5、无状态
二、TCP/IP三次握手和四次挥手的原理和状态转换过程
1、三次握手,是建立连接过程
(1)、第一次握手,client将报文标志位SYN置为1,并随机生成seq=i,将数据包发送给server,自身进入SYN_SENT状态,等待确认
(2)、server端接收到报文后,由SYN=1知道client端请求连接,服务端将标志位SYN=1和ACK=1,确认号=i+1,并且随机生成seq=k,
将报文发给client端确认连接,server端进入SYN_RCVD状态
(3)、client接收到报文后,检查确认号是否为i+1,如果是,则将标志位ACK=1,确认号=k+1,将报文发给server,
并且进入ESTABLISHED状态,server端接收到报文后,也进入ESTABLISHED状态,完成握手连接。
2、四次挥手
(1)、第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)、第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)、第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)、第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
1、 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
2、 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为:虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。
LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
SYN_SENT: 当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。(发送端)
SYN_RCVD: 这个状态与SYN_SENT遥想呼应这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个 ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。(服务器端)
ESTABLISHED:这个容易理解了,表示连接已经建立了。
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)
CLOSING(比较少见): 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)
CLOSED: 表示连接中断。
三、epoll/poll/select原理和使用逻辑
1、epoll,为了处理大批量文件句柄而做改进的poll。
select在一个进程里对于打开FD(文件描述句柄)是有限制的,由FD_SETSIZE设置,默认值是1024。可以通过创建大量进程解决,但会消耗大量系统资源,而且进程切换消耗比线程大。
poll虽然没有select的限制,最大可以打开跟系统一样大(cat /proc/sys/fs/file-max),但是poll和select同样都存在相同问题的是当存在大量socket时候,有部分触发时,都会线性遍历所有的FD集合。
使用epoll就不会存在问题,内核里会在每个FD上实现callback函数,当socket激活时会调用相应的FD的callback函数,激活FD,当我们调用epoll_wait函数时候,会返回激活的FD数量的值,然后去指定的数组中取得相应数量的描述符,这里使用到内存映射(mmap)技术,不用线性遍历,
http://blog.csdn.net/xiajun07061225/article/details/9250579
2、epoll使用内存共享,避免内核拷贝
3、epoll使用回调函数,有数据的时候,内核调用回调函数把内核数据拷贝到用户层缓存列表中,epoll_wait检查时从缓存列表是否有数据即可
四、滑动窗口
滑动窗口用来控制TCP的传输速率、保证TCP传输可靠性,TCP缓存数据可以分为4类,已发送并且得到ACK确认、已发送未得到ACK确认、为发送但对方允许发送的、未发送也未允许发送的。已发送未得到ACK确认,为发送但对方允许发送的这两部分的数据称为窗口数据,发送数据后必须得到对方ACK确认后窗口才能向右移动,否则超时重发,保证数据可靠性。
滑动窗口实现面向流的可靠性
最基本的传输可靠性来源于“确认重传”机制。
TCP的滑动窗口的可靠性也是建立在“确认重传”基础上的。
发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。
五、Linux下五种IO模式/异步模式
1、同步阻塞I/O 2、同步非阻塞I/O 3、I/O复用(select和poll) 4、信号驱动I/O(SIGIO) 5、异步I/O(Posix.1的aio_系列函数)
广告:恒生招聘,感兴趣想内推的请查看 http://my.oschina.net/u/190601/blog/616403