1 系统调用和应用编程接口
1.1 系统调用
大多数操作系统使用系统调用(system call)的机制在应用程序和操作系统之间传递控制权。
当某个应用进程启动系统调用时,控制权就从应用进程传递给了系统调用接口。此接口再把控制权传递给计算机的操作系统。操作系统把这个调用转给某个内部过程,并执行所请求的操作。内部过程一旦执行完毕,控制权就又通过系统调用接口返回给应用进程。
系统调用接口实际上就是应用进程的控制权和操作系统的控制权进行转换的一个接口。
1.2 应用编程接口 API
由于应用程序在使用系统调用之前要编写一些程序,特别是需要设置系统调用中的许多参数,因此这种系统调用接口又称为应用编程接口 API (Application Programming Interface)。
API 从程序设计的角度定义了许多标准的系统调用函数。应用进程只要使用标准的系统调用函数就可得到操作系统的服务。因此从程序设计的角度看,也可以把 API 看成是应用程序和操作系统之间的接口。
1.3 TCP/IP 协议 API
由于 TCP/IP 协议族被设计成能运行在多种操作系统的环境中,TCP/IP 协议允许系统设计者选择应用程序与 TCP/IP 协议软件的接口 API 的具体实现细节。
目前,只有几种可供应用程序使用 TCP/IP 的应用编程接口API。
- 套接字接口(socket interface)
- 美国加利福尼亚大学伯克利分校为 Berkeley UNIX 操作系统定义的一种 API
- Windows socket(WinSock)
- 微软公司在其操作系统中采用了套接字接口 API,形成了一个稍有不同的 API,并称之为 Windows socket,简称为 WinSock
- TLI (Transport Layer Interface)
- AT&T 为其 UNIX 系统 V 定义的一种 API
在讨论网络编程时常常把套接字作为应用进程和运输层协议之间的接口,现在套接字己成为计算机操作系统内核的一部分。
在套接字以上的进程是受应用程序控制的,而在套接字以下的运输层协议软件则是受计算机操作系统的控制。
1.4 socket 套接字
套接字是应用进程为了获得网络通信服务而与操作系统进行交互时使用的一种机制。
- socket 系统调用
- 当应用进程(客户或服务器)需要使用网络进行通信时,必须首先发出 socket 系统调用,请求操作系统为其创建一个“套接字”。
- 这个调用的实际效果是请求操作系统把网络通信所需要的一些系统资源(存储器空间、CPU时间、网络带宽等)分配给该应用进程。
- 应用进程通过一个关闭套接字的 close 系统调用通知操作系统回收与该套接字描述符相关的所有资源。
- 套接字描述符
- 操作系统为这些资源的总和用一个叫做套接字描述符(socket descriptor)的号码(小的整数)来表示,然后把这个套接字描述符返回给应用进程。
- 应用进程所进行的网络操作(建立连接、收发数据、调整网络通信参数等)都必须使用这个套接字描述符。
- 操作系统通过套接字描述符识别应该
2 几种常用的系统调用
以使用 TCP 的服务为例
2.1 连接建立阶段
服务器
- bind
- 调用 bind(绑定)来指明套接字的本地地址(本地端口号和本地IP地址)
- 在服务器端调用 bind 时就是把熟知端口号和本地IP地址填写到己创建的套接字中。
- 在客户端也可以不调用 bind,这时由操作系统内核自动分配一个动态端口号(通信结束后由系统收回)。
- listen
- 服务器在调用 bind 后,还必须调用 listen(收听)把套接字设置为被动方式,以便随时接受客户的服务请求。
- UDP服务器由于只提供无连接服务,不使用listen系统调用。
- accept
- 服务器紧接着就调用 accept(接受),以便把远地客户进程发来的连接请求提取出来。
- 系统调用 accept 的一个变量就是要指明是从哪一个套接字发起的连接。
- 主服务器进程用原来的套接字接受连接请求,而从属服务器进程用新创建的套接字和相应的客户建立连接并可进行双向传送数据。
客户端
- connect
- 当使用 TCP 协议的客户己经调用 socket 创建了套接字后,客户进程就调用 connect,以便和远地服务器建立连接(这就是主动打开,相当于客户发出的连接请求)。
- 在 connect 系统调用中,客户必须指明远地端点(即远地服务器的IP地址和端口号)
2.2 数据传送阶段
- send
- 客户使用 send 发送请求,而服务器使用 send 发送回答
- recv
- 服务器使用 recv 接收客户用 send 调用发送的请求
- 客户在发完请求后用 recv 接收回答。
2.3 连接释放阶段
- close
- 一旦客户或服务器结束使用套接字,就把套接字撤销。这时就调用 close 释放连接和撤销套接字。