常或强迫终止。
2.2.4 套接字类型
TCP/IP 的 socket 提供下列三种类型套接字。
流式套接字
流式套接字流式套接字
流式套接字(
((
(SOCK_STREAM)
))
)
提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。
内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用
流式套接字。
数据报式套接字
数据报式套接字数据报式套接字
数据报式套接字(
((
(SOCK_DGRAM)
))
)
提供了一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,
并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。
原始式套接字
原始式套接字原始式套接字
原始式套接字(
((
(SOCK_RAW)
))
)
该接口允许对较低层协议,如 IP、ICMP 直接访问。常用于检验新的协议实现或访问现有服务中
配置的新设备。
2.3 基本套接字系统调用
为了更好地说明套接字编程原理,下面给出几个基本套接字系统调用说明。
2.3.1 创建套接字──socket()
应用程序在使用套接字前,首先必须拥有一个套接字,系统调用 socket()向应用程序提供创建套接
字的手段,其调用格式如下:
SOCKET PASCAL FAR socket(int af, int type, int protocol);
该调用要接收三个参数:af、type、protocol。参数 af 指定通信发生的区域,UNIX 系统支持的地
址族有:AF_UNIX、AF_INET、AF_NS 等,而 DOS、WINDOWS 中仅支持 AF_INET,它是网际网区
域。因此,地址族与协议族相同。参数 type 描述要建立的套接字的类型。参数 protocol 说明该套接字
使用的特定协议,如果调用者不希望特别指定使用的协议,则置为 0,使用默认的连接模式。根据这
三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此,socket()系
统调用实际上指定了相关五元组中的“协议”这一元。
有关 socket()的详细描述参看 5.2.23。
2.3.2 指定本地地址──bind()
当一个套接字用 socket()创建后,存在一个名字空间(地址族),但它没有被命名。bind()将套接字地
址(包括本地主机地址和本地端口地址)与所创建的套接字号联系起来,即将名字赋予套接字,以指
定本地半相关。其调用格式如下:
int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);
参数 s 是由 socket()调用返回的并且未作连接的套接字描述符(套接字号)。参数 name 是赋给套接
字 s 的本地地址(名字),其长度可变,结构随通信域的不同而不同。namelen 表明了 name 的长度。
如果没有错误发生,bind()返回 0。否则返回值 SOCKET_ERROR。
地址在建立套接字通信过程中起着重要作用,作为一个网络应用程序设计者对套接字地址结构必
须有明确认识。例如,UNIX BSD 有一组描述套接字地址的数据结构,其中使用 TCP/IP 协议的地址结
构为:
struct sockaddr_in{
short sin_family; /*AF_INET*/
u_short sin_port; /*16 位端口号,网络字节顺序*/
struct in_addr sin_addr; /*32 位 IP 地址,网络字节顺序*/
char sin_zero[8]; /*保留*/
}
有关 bind()的详细描述参看 5.2.2。
2.3.3 建立套接字连接──connect()与 accept()
这两个系统调用用于完成一个完整相关的建立,其中 connect()用于建立连接。无连接的套接字进
程也可以调用 connect(),但这时在进程之间没有实际的报文交换,调用将从本地操作系统直接返回。
这样做的优点是程序员不必为每一数据指定目的地址,而且如果收到的一个数据报,其目的端口未与
任何套接字建立“连接”,便能判断该端口不可操作。而 accept()用于使服务器等待来自某客户进程的
实际连接。
connect()的调用格式如下: