socket-通信过程及流程1_第1页
socket-通信过程及流程1_第2页
socket-通信过程及流程1_第3页
socket-通信过程及流程1_第4页
socket-通信过程及流程1_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

socket通信过程及流程

卜・图是基于TCP协议的客户端/服务器程序的一般流程:

展务驾端应用层

listenfd-sockets

分配-个文徉硒符

binddistenfd,联弟等地址浇口)

辨定istenf曲海城

自存地址任意

listendistenfd,琳度)

使listenfd成为一个监听病述符

connfd-acceptdistenfd.客用出期口)

困爰等待客户希f接

accept返回

分配斩的向S承。nnfdW户襦通信

read(connfd.buf,size)"

阻塞等待客户微据清浪

readj§0箱坏

处屏户端话求多次

writetconnfd,but.size)

发送或据点M

read(connfd.buf.size)

闲兖等待客户都据诺求

rea施回0

close(connfd)

服务器调用socket()、bind()、listen()完成初始化后,调用accept。阻塞等待,处于监听端口的状态,客

户端调用socket。初始化后,调用connect。发出SYN段并阻塞等待服务器应答,服务器应答•个

SYN-ACK段,客户端收到后从connect。返回,同时应答一个ACK段,服务器收到后从accept。返回。

数据传输的过程:

建立连接后,TCP协议提供全双工的通信服务,但是•般的客户端/服务腓程序的流程是由客户端主动

发起请求,服务器被动处理请求,一问一答的方式。因此服务器从accept。返回后立刻调用read。,

读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write。发送请求给服务器,

服务器收到后从read。返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器

的应答,服务器调用write。将处理结果发回给客户端,再次调用read。阻塞等待下一条请求,客户端

收到后从read。返回,发送下一条请求,如此循环下去。

如果客户端没有更多的请求了,就调用close。关闭连接,就像写端关闭的管道一样,服务器的read。

返回0,这样服务器就知道客户端关闭了连接,也调用close。关闭连接。注意,任何一方调用close。

后,连接的两个传输方向都关闭,不能再发送数据了。如果功.调用shutdown。则连接处于半关闭状

态,仍可接收对方发来的数据。

在学习socketAPI时要注意应用程序和TCP协议层是如何交互的:*应用程序调用某个socket函数

时TCP协议层完成什么动作,比如调用connect。会发出SYN段•应用程序如何知道TCP协议层的

状态变化,比如从某个阻塞的socket函数返回就表明TCP协议收到了某些段,再比如read。如回0

就表明收到了FIN段

看图所示的-socket通信过程

server一方的socketclient一方的socket

图12.9socket的通信过程

1.建立套接字

在sys/socket.h中。

intsocket(intfamily,inttype,intprotocol);

socket。打开一个网络通讯端口,如果成功的话,就像open。一样返回一个文件描述符,应用程序可

以像读写文件一样用read/write在网络上收发数据,如果socket。调用出错则返回-1“对于IPv4,

family参数指定为AFJNEK对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输

协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议,protocol

参数的介绍从略,指定为0即可。

Linux在利用socket。系统调用建立新的套接字时,需要传递套接字的地址族标识符、套接字类型以

及协议,其函数定义于net/socket.c中:

asmlinkagelongsys_socket(intfamily,inttype,intprotocol1

intretval;

structsocket*sock;

retval=sock_create(family,type,protocol,&sock);

if(retval<0)

gotoout;

retval=sock_map_fd(sock);

if(retval<0)

gotoout_release;

out:

/.l.ma.b.alread.anothe.descripto.8.Nblem.*/

returnretval;

outrelease:

sock_release(sock);

returnretval;

}

实际上,套接字对于用户程序而言就是特殊的已打开的文件。内核中为套接字定义了一种特殊的文

件类型,形成一种特殊的文件系统sockfs,其定义于net/socket.c:

staticstructvfsmount*sock_mnt;

staticDECLARE_FSTYPE(sock_fs_type,"sockfs",sockfs_read_super,FS_NOMOUNT);

在系统初始化时,要通过kern_mount()安装这个文件系统。安装时有个作为连接件的vfsmount数

据结构,这个结构的地址就保存在一个全局的指针sock_mnt中。所谓创建一个套接字,就是在sockfs

文件系统中创建一个特殊文件,或者说一个节点,并建立起为实现套接字功能所需的一整套数据结构。

所以,函数sock_create()首先是建立一个socket数据结构,然后将其“映射”到一个已打开的文件

中,进行socket结构和sock结构的分配和初始化。

新创建的BSDsocket数据结构包含有指向地址族专有的套接字例程的指针,这一指针实际就是

proto_ops数据结构的地址。

BSD套接字的套接字类型设置为所请求的SOCK_STREAM或SOCK_DGRAM等。然后,内核利

用proto_ops数据结构中的信息调用地址族专有的创建例程。

之后,内核从当前进程的fd向量中分配空闲的文件描述符,该描述符指向的file数据结构被初始化。

初始化过程包括将文件操作集指针指向由BSD套接字接口支持的BSD文件操作集。所有随后的套

接字(文件)操作都将定向到该套接字接口,而套接字接口则会进一步调用地址族的操作例程,从而

将操作传递到底层地址族,如图12.10所示。

flles.slrucl

closeonexec

openA

BSD套鞭子

文件,作票

bt«kioc"

re«dclott

writefMync

faodeselect

fHMioa

SOCK.STREAM地址嫉

SOCKSTREAM

protocol

实际上,socket结构与sock结构是同一事物的两个方面。如果说socket结构是面向进程和系统调用

界面的,那么sock结构就是面向底层驱动程序的。可是,为什么不把这两个数据结构合并成•个呢?

我们说套接字是一种特殊的文件系统,Wilt,inode结构内部的union的一个成分就用作socket结构,

其定义如下:

structinode

union{

structsocketsocketj;

)

由于套接字操作的特殊性,这个结构中需要大量的结构成分。可是,如果把这些结构成分全都放在

socket结构中,则inode结构中的这个union就会变得很大,从而inode结构也会变得很大,而对于

其他文件系统,这个union成分并不需要那么庞大。因此,就把套接字所需的这些结构成分拆成两部

分,把与文件系统关系比较密切的那一部分放在socket结构中,把与通信关系比较密切的那一部分则

单独组成•个数据结构,即sock结构。由于这两部分数据在逻辑上本来就是•体的,所以要通过指针

互相指向对方,形成一对一的关系。

2.在INETBSD套接字上绑定(bind)地址

为了监听传入的Internet连接请求,每个服务器都需要建立一个INETRSD套接

字,并且将自己的地址绑定到该套接字。绑定操作主要在INET套接字层中进行,

还需要底层TCP层和IP层的某些支持。将地址绑定到某个套接字上之后,该套

接字就不能用来进行任何其他的通讯,因此,该socket数据结构的状态必须为

TCP_CLOSE。传递到J绑定操作的sockaddr数据结构中包含要绑定的IP地址,以

及一个可选的端口地址。通常而言,要绑定的地址应该是赋予某个网络设备的IP

地址,而该网络设备应该支持INET地址族,并且该设备是可用的。利用ifconfig

命令可查看当前活动的网络接口。被绑定的IP地址保存在sock数据结构的

rcv_saddr和saddr域中,这两个域分别用丁哈希直找和发送用的IP地址。端口

地址是可选的,如果没有指定,底层的支持网络会选择一个空闲的端口。

intbind(intsockfd,conststructsockaddr*myaddrzsocklent

addrlen);

服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端

口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号。bind。

成功返回0,失败返回7。

bind。的作用是将参数sockfd和myaddr绑定在一起,使sockfd这个用于网络通讯

的文件描述符监听myaddr所描述的地址和端口号。前面讲过,structsockaddr*是

一个通用指针类型,myaddr参数实际上可以接受多种协议的sockaddr结构体,而它

们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度。我们的程序中

对myaddr参数是这样初始化的:

bzero(&servaddr,sizeof(servaddr));

servaddr.sin_family=AF_INET;

servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

servaddr.sin_port=htons(SERV_P0RT);

首先将整个结构体清零,然后设置地址类型为AF_INET,网络地址为INADDR_ANY,这个宏表示本

地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在

所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为

SERV_PORT,我们定义为8000。

当底层网络设备接受到数据包时,它必须将数据包传递到正确的INET和BSD套接字以便进吁处

理,因此,TCP维护多个哈希表,用来查找传入IP消息的地址,并将它们定向到正确的socket/sock

对。TCP并不在绑定过程中将绑定的sock数据结构添加到哈希表中,在这一过程中,它仅仅判断所

请求的端口号当前是否正在使用。在监听操作中,该sock结构才被添加到TCP的哈希表中。

3.在INETBSD套接字上建立连接(connect)

创建一个套接字之后,该套接字不仅可以用于监听入站的连接请求,也可以用于

建立出站的连接请求。不论怎样都涉及到一个重要的过程:建立两个应用程序之间

的虚拟电路。出站连接只能建立在处于正确状态的INETBSD套接字上,因此,不

能建立于已建立连接的套接字,也不能建立于用于监听入站连接的套接字。也就是

说,该BSDsocket数据结构的状态必须为SS_UNC0NNECTEDo

在建立连接过程中,双方TCP要进行三次“握手”,具体过程在本章第二节一

网络协议一文中有详细介绍。如果TCPsock正在等待传入消息,则该sock结构

添加到tcp_listening_hash表中,这样,传入的TCP消息就可以定向到该sock

数据结构。

由于客户端不需要固定的端口号,因此不必调用bind。,客户端的端口号由内核自

动分配。注意,客户端不是不允许调用bind。,只是没有必要调用bind。固定一个端

口号,服务器也不是必须调用bind(),但如果服务器不调用bind(),内核会自动给服

务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会

遇到麻烦。

intconnect(intsockfd,conststructsockaddr*servaddr,

socklentaddrlen);

客户端需要调用connect。连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自

己的地址,而connect的参数是对方的地址。connect。成功返回0,出错返回-1。

4.监听(listen)INETBSD套接字

intlisten(intsockfd,intbacklog);

典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept。返回

并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未accept的客户端就处于

连接等待状态,listen。声明sockfd处于监听状态,并且最多允许有backlog个客户端处于连接待状态,

如果接收到更多的连接请求就忽略。listen。成功返回0,失败返回-1。

当某个套接字被绑定了地址之后,该套接字就可以用来监听专属于•该绑定地址的传入连接。网络应

用程序也可以在未绑定地址之前监听套接字,这肘,INET套接字层将利用空闲的端口编号并自动绑

定到该套接字。套接字的监听函数将socket的状态改变为TCP_LISTENo

当接收到某个传入的TCP连接请求时,TCP建汇•个新的sock数据结构来描述该连接。当该连接

最终被接受时,新的sock数据结构将变成该TCP连接的内核bottom_half部分,这时,它要克隆

包含连接请求的传入sk_buff中的信息,并在监听sock数据结构的receive_queue队列中将克隆

的信息排队。克隆的sk_buff中包含有指向新sock数据结构的指针。

5.接受连接请求(accept)

接受操作在监听套接字上进行,从监听socket中克隆一个新的socket数据结构。

其过程如下:接受操作首先传递到支持协议层,即

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论