概述
Socket的英文原意是“孔”或“插座”,现在,作为Unix的进程通信机制,常常取“插座”这一意义。日常生活中常见的插座,有的是信号插座,有的是电源插座,有的可以接收信号或能量,有的可以发送信号或能量。举例来说,电话线与电话机之间需要一个插座(相当于两者之间的接口,这一部分装置物理上是存在的)。对于网络编程,socket就相当于电话线与电话机之间的插座。
将电话系统与面向连接的Socket机制相比,两者之间有着惊人的相似的地方。以一个国家的电话网为例。电话的通信双方相当于互相通信的两个进程;通话双方所在的地区(享有一个全局唯一的区号)相当于一个网络,区号即是其网络地址;区内的一个单位的交换机相当于一台主机,交换机分配给每个用户的局内号码就相当于主机运行中分配给进程的socket号。
任何用户在通话之前,首先应该有一部电话机,相当于申请一个socket号;同时,还必须直到对方的电话号码,此电话号码对应于对方的电话机,该电话机也必须申请一个socket号。申请socket号的过程就是将电话线插入电话机的通信串口的过程。然后,用户拨号呼叫对方,此时相当于发出连接请求(如果对方不在本地区,在对方电话号码前还应该附加上对方所在地区的区号,此区号相当于给出网络地址)。如果对方在电话机处并且空闲(相当于通信的目的主机开机且可以接受连接请求),拿起电话话筒,双方就可以正是通话,即连接成功。双方通话的过程,是电话机通过接口发送信号和从接口接收信号的过程,相当于向socket发送数据和从socket接收数据。当通话结束后,一方挂机,相当于接口阻塞,socket关闭,从而撤销连接。
在电话系统中,一般用户只能感受到本地电话机和对方电话号码的存在,建立通话的过程、话音传输的过程以及整个电话系统的技术细节对用户而言是封装的,不透明的,用户与用户之间的电话仅通过通信协议和电话号码实现。这一机制与socket机制非常相似。socket利用网络通信设施实现进程间通信,但它对于通信设施的具体细节并不关心,只要底层通信设施能够提供足够的通信能力,socket便能够进行基本的网络通信功能。
至此,我们队socket进行了直观的描述。抽象出来,socket实质上提供了进程间通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没法建立联系并相互通信的。正如电话系统一样,双方的通话是建立在通话双方均各自拥有一台电话机一样。
每一个socket都用一个半相关描述:
socket(通信协议,本地地址,本地端口);
一个完整的socket则用一个相关描述:
socket(通信协议,本地地址,本地端口,远程地址,远程端口);
每一个socket都有一个本地唯一的socket号,该socket号由操作系统进行分配和管理。
最重要的是,socket是面向客户端/服务器模型而设计的,针对客户端和服务器程序提供不同的socket系统调用。客户端随机申请一个socket号(相当于一个想打电话的人可以在任何一部入网的电话机上拨号呼叫);服务器拥有公认的socket,任何客户都可以向它发出连接请求和信心传输请求(相当于一个被叫电话拥有一个呼叫方知道的电话号码)。
Socket利用客户端/服务器模型巧妙地解决了进程之间建立通信连接的问题。服务器socket为众所周知且非常重要的。无论如何,通信双方至少有一方知道对方的socket信息(主要指网络地址和端口号)。
套接字的类型及对应流程
传输层协议主要分为TCP协议和UDP协议。由TCP向应用程序提供的服务不同于UDP提供的服务。
首先,TCP提供客户端和服务器之间的连接(connection)。TCP客户端先与某个给定服务器建立一个连接,再跨该连接与服务器交换数据,然后终止该连接。
其次,TCP提供可靠性(reliability)。当TCP向另一端发送数据时,它要求对端返回确认信息,如果没有收到确认,TCP就自动重传数据并等待更长时间。在数次重传失败后,TCP才放弃。
再则,TCP提供流量控制(flow control)。
最后,TCP连接是全双工的,这意味着一个给定的连接上应用可以在任何时刻在进出两个方向上发送和接收数据。
套接字有三种类型:流式套接字(SOCK_STREAM)、数据报套接字(SOCK_DGRAM)和原始套接字。
1、SOCK_STREAM(TCP适用)
流式套接字(SOCK_STREAM)提供可靠的、面向连接的通信。其使用了TCP协议。
其建立连接与传输的过程如下图:
2、SOCK_DGRAM(UDP适用)
数据报套接字(SOCK_DGRAM)定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠性。
数据报套接字为什么“无连接”和“不可靠”?
*发送的数据报可能不会到达指定目的主机;
*数据报可能会以不同顺序到达;
*到达目的主机的数据报可能存在错误。
数据报套接字使用UDP协议。
其数据传输流程如下图:
3、原始套接字
原始套接字主要用于一些协议的开发,可以进行比较底层的操作。它功能强大,但是没有上面介绍的两种套接字使用方便,一般的程序也涉及不到原始套接字。
套接字描述符
1、什么是套接字?
套接字是通过标准的unix文件描述符与其它的程序进行通信的一种方法(其它的进程间通信方法包括管道等)。
2、Socket描述符
在Unix系统中,任何对I/O的操作,都是通过读或写一个文件描述符来实现的。一个文件描述符只是一个简单的整形数值,代表一个被打开的文件(这里的文件是广义上的文件,并不只是代表磁盘文件,而且代表一个网络连接,一个先进先出的队列,一个终端显示屏幕以及其它的一切)。在Unix系统中,任何东西都是文件。
因此,在这里,我们应该建立这样一种概念,那就是socket是文件,socket描述符是文件描述符。
Unix网络编程 之 socket简介