Unix Socket编程简介

来源:互联网 发布:陪我聊天软件 编辑:程序博客网 时间:2024/04/30 09:50
阅读本文需要对TCP有基本的了解,对TCP连接的建立、断开,以及TCP运行过程中状态转换不了解的童鞋可以首先阅读我的另一篇博客:

http://blog.csdn.net/jiwang1990/article/details/39234757

Unix/Linux操作系统暴露给应用层的网络编程接口是Socket,下面我们对Socket编程进行个简单的介绍;Client/Server编程模型是使用最广泛的编程模型,其过程如下图所示:

下面我们将这幅图中的相关函数调用映射到TCP连接的建立和断开过程中:



Socket API概述

1创建套接字——socket函数

应用程序在使用套接字前,必须拥有一个套接字,系统调用 socket ()向应用程序提供

创建套接字的手段,其调用格式如下:

e.JPG

参数 family 指定通信发生的区域, UNIX 系统支持的地址族有: AF_UNIX,AF_INET,AF_NS 等,而 DOS 、 WINDOWS 中仅支持 AF_INET ,它是网际网区域。因此,地址族与协议族相同。

参数 type 描述要建立的套接字的类型。参数 protocol 说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为 0 ,使用默认的连接模式。根据这 3 个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此, socket ()系统调用实际上指定了 " 协议 " 。

f.JPG

2 指定本地址—— bind 函数

一个套接字用 socket ()创建后,存在一个名字空间(地址族),但它没有被命名。 Bind ()将套接字地址(包括本地主机地址和本断口地址)与所创建的套接字号联系起来,即将,名字赋予套接字,以指定本地半相关。其调用格式如下:

g.JPG

参数 socketfd 是由 socket() 调用返回的并且未作连接的套接字描述符(套接字号)。参数 myaddr 是赋给套接字 socketfd 的本地地址(名字),其长度可变,结构随通信域的不同而不同。 addrlen 表明了 name 的长度。

进程可以把一个特定的 IP 地址捆绑到它的套接口上,但此 IP 地址必须是主机的一个接口。对于 TCP 客户端,这就为在此套接口上发送的 IP 数据包分配了源 IP 地址。对于服务器端,这样做就限制了套接口只接收来自那些目的地址为此 IP 地址的客户链接。

对于 TCP ,调用函数 bind 可以指定一个端口号,指定一个 IP 地址,可以两者都指定,也可以一个都不指定。对于服务器,一般指定众所周知的端口号。而不指定具体的 IP 地址。如果 TCP 服务器不把地址绑到套接口上,那么内核就把客户所发 SYN 所在分组的目的 IP 地址作为服务器的源 IP 地址。

若指定端口号为 0 ,则调用函数 bind 时,内核选择一个临时端口;但若指定一个通配 IP 地址,则直到套接口以连接 (TCP) 或数据报已在套接口上发出 (UDP), 内核才选择一个本地 IP 。

注意到在第四部分图中,客户端并没有调用 bind 函数,因为对于客户端来说,没有必要指定具体的 IP 和端口,如果需要,内核会选择一个源 IP 地址和一个临时的端口。

h.JPG

3 connect 函数

TCP 客户用 connect() 函数建立一个与 TCP 服务器的链接。 Connect ()的调用格式如下:

i.JPG

参数 socket 是欲建立连接的本地套接字描述符。参数 servaddr 指出说明对方套接字地址结构指针。对方套接字地址长度由 addrlen 说明。

根据 TCP 的状态转移图,函数 connect 导致从 CLOSED 状态 ( 调用函数 socket 创建套接口以后就一直处于此状态 ) 转到 SYN_SENT 状态,若成功转到 ESTABLISHED 状态。如果函数 connect 失败,则原先创建的套接口就不可再用,必须关闭。如要重新尝试,必须重新调用 socket ,再 connect 。

4 listen 函数

函数 listen 仅被 TCP 服务器调用,它做两件事情:

1. 当函数socket创建一个套接口时,它被假设为一个主动套接口,也就是说,它是一个将调用connect发起链接的客户套接口。函数listen将未链接的套接口转换成被动套接口,告诉内核应接受指向此套接口的链接请求。根据TCP状态转移图,函数listen导致套接口状态从CLOSED转到LISTEN。

2. 函数的第二个参数规定了内核为此套接口排队的最大链接个数

j.JPG

一般而言,此函数应该在 socket 和 bind 之后,调用函数 accept 之前调用。

参数 backlog 的解析:

对于给定的监听套接口 (listen 之后 ) ,内核要维护两个队列:一个是处于三次握手过程中(即客户端调用 connect ,服务器端收到 SYN ,并返回 ACK 和 SYN 后,在等待客户端的 ACK ),处于 SYN_RCVD 状态;另一个是从 connect 成功,处于 ESTABLISHED 状态。

两个队列之和不能超过 backlog 。

k.JPG

5 accept 函数

Accept 函数由 TCP 服务器调用,从已完成连接队列头返回一个已完成的链接。若已完成队列为空,则进程睡眠(假定套接口为缺省的阻塞方式)。用于使服务器等待来自某客户进程的实际连接。

l.JPG

参数 cliaddr 和 addrlen 用来返回链接对方进程(客户端)的协议地址。

若函数成功返回,返回值是一个由内核自动生成的全新的描述字,代表与客户端的链接。当我们讨论函数 accept 时,常把它的第一个参数称为监听套接口描述字(由 socket 生成的描述字);把它的返回值称为已连接套接口描述字。


本文后半部分均为转载,原文地址为:http://www.cnitblog.com/tarius.wu/articles/434.html

0 0
原创粉丝点击