socket实现原理和机制

要写网络程序就必须用Socket,这是程序员都知道的。并且,面试的时候,咱们也会问对方会不会Socket编程?通常来讲,不少人都会说,Socket编程基本就是listen,accept以及send,write等几个基本的操做。是的,就跟常见的文件操做同样,只要写过就必定知道。

对于网络编程,咱们也言必称TCP/IP,彷佛其它网络协议已经不存在了。对于TCP/IP,咱们还知道TCP和UDP,前者能够保证数据的正确和可靠性,后者则容许数据丢失。最后,咱们还知道,在创建链接前,必须知道对方的IP地址和端口号。除此,普通的程序员就不会知道太多了,不少时候这些知识已经够用了。最多,写服务程序的时候,会使用多线程来处理并发访问。

咱们还知道以下几个事实:
1。一个指定的端口号不能被多个程序共用。好比,若是IIS占用了80端口,那么Apache就不能也用80端口了。
2。不少防火墙只容许特定目标端口的数据包经过。
3。服务程序在listen某个端口并accept某个链接请求后,会生成一个新的socket来对该请求进行处理。

因而,一个困惑了我好久的问题就产生了。若是一个socket建立后并与80端口绑定后,是否就意味着该socket占用了80端口呢?若是是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直觉得系统会默认给其分配一个空闲的端口号)?若是是一个空闲的端口,那必定不是80端口了,因而之后的TCP数据包的目标端口就不是80了--防火墙必定会组织其经过的!实际上,咱们能够看到,防火墙并无阻止这样的链接,并且这是最多见的链接请求和处理方式。个人不解就是,为何防火墙没有阻止这样的链接?它是如何断定那条链接是由于connet80端口而生成的?是否是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?

后来,我又仔细研读了TCP/IP的协议栈的原理,对不少概念有了更深入的认识。好比,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End to End)的数据包传送,这里的节点是一台网络设备,好比计算机。由于IP层只负责把数据送到节点,而不能区分上面的不一样应用,因此TCP和UDP协议在其基础上加入了端口的信息,端口因而标识的是一个节点上的一个应用。除了增长端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,好比滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。无论应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,须要由TCP协议来进行数据重组。

因此,我有理由怀疑,防火墙并无足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。并且,咱们也看到,所谓的端口,是为了区分不一样的应用的,以在不一样的IP包来到的时候可以正确转发。

TCP/IP只是一个协议栈,就像操做系统的运行机制同样,必需要具体实现,同时还要提供对外的操做接口。就像操做系统会提供标准的编程接口,好比Win32编程接口同样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口--原来是这么回事啊!

Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很类似,实际上在BSD系统里就是跟文件句柄同样存放在同样的进程句柄表里。这个socket实际上是一个序号,表示其在句柄表中的位置。这一点,咱们已经见过不少了,好比文件句柄,窗口句柄等等。这些句柄,实际上是表明了系统中的某些特定的对象,用于在各类函数中做为参数传入,以对特定的对象进行操做--这实际上是C语言的问题,在C++语言里,这个句柄其实就是this指针,实际就是对象指针啦。

如今咱们知道,socket跟TCP/IP并无必然的联系。Socket编程接口在设计的时候,就但愿也能适应其余的网络协议。因此,socket的出现只是能够更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,造成了几个最基本的函数接口。好比create,listen,accept,connect,read和write等等。

如今咱们明白,若是一个程序建立了一个socket,并让其监听80端口,实际上是向TCP/IP协议栈声明了其对80端口的占有。之后,全部目标是80端口的TCP数据包都会转发给该程序(这里的程序,由于使用的是Socket编程接口,因此首先由Socket层来处理)。所谓accept函数,其实抽象的是TCP的链接创建过程。accept函数返回的新socket其实指代的是本次建立的链接,而一个链接是包括两部分信息的,一个是源IP和源端口,另外一个是宿IP和宿端口。因此,accept能够产生多个不一样的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些socket宿端口就能够都是80,而Socket层仍是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操做封装!而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。

明白socket只是对TCP/IP协议栈操做的抽象,而不是简单的映射关系,这很重要!



一、TCP链接
手机可以使用联网功能是由于手机底层实现了TCP/IP协议,可使手机终端经过无线网络创建TCP链接。TCP协议能够对上层网络提供接口,使上层网络数据的传输创建在“无差异”的网络之上。

创建起一个TCP链接须要通过“三次握手”:

第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时本身也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程当中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP链接一旦创建,在通讯双方中的任何一方主动关闭链接以前,TCP 链接都将被一直保持下去。断开链接时服务器和客户端都可以主动发起断开TCP链接的请求,断开过程须要通过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终肯定断开)


二、HTTP链接

HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网经常使用的协议之一,HTTP协议是创建在TCP协议之上的一种应用。

HTTP链接最显著的特色是客户端发送的每次请求都须要服务器回送响应,在请求结束后,会主动释放链接。从创建链接到关闭链接的过程称为“一次链接”。

1)在HTTP 1.0中,客户端的每次请求都要求创建一次单独的链接,在处理完本次请求后,就自动释放链接。
2)在HTTP 1.1中则能够在一次链接中处理多个请求,而且多个请求能够重叠进行,不须要等待一个请求结束后再发送下一个请求。
因为HTTP在每次请求结束后都会主动释放链接,所以HTTP链接是一种“短链接”,要保持客户端程序的在线状态,须要不断地向服务器发起链接请求。一般的作法是即时不须要得到任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持链接”的请求,服务器在收到该请求后对客户端进行回复,代表知道客户端“在线”。若服务器长时间没法收到客户端的请求,则认为客户端“下线”,若客户端长时间没法收到服务器的回复,则认为网络已经断开。


三、SOCKET原理

3.1套接字(socket)概念
套接字(socket)是通讯的基石,是支持TCP/IP协议的网络通讯的基本操做单元。它是网络通讯过程当中端点的抽象表示,包含进行网络通讯必须的五种信息:链接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

应用层经过传输层进行数据通讯时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP链接或多个应用程序进程可能须要经过同一个 TCP协议端口传输数据。为了区别不一样的应用程序进程和链接,许多计算机操做系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层能够和传输层经过Socket接口,区分来自不一样应用程序进程或网络链接的通讯,实现数据传输的并发服务
程序员

相关文章
相关标签/搜索