socket-通信过程及流程
本作品内容为socket-通信过程及流程,格式为 docx ,大小 222196 KB ,页数为 9页
('页眉内容socket通信过程及流程下图是基于TCP协议的客户端/服务器程序的一般流程:服务器调用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\x7f通信过程图12.9socket的通信过程1.建立套接字在sys/socket.h中。intsocket(intfamily,inttype,intprotocol);根据工程勘察报告揭露,本场地自地表至持力层深度范围内所揭露的土层主要由饱和粘土、砂土组成,具有成层分布的特点。页脚内容页眉内容socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。对于IPv4,family参数指定为AF_INET。对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。protocol参数的介绍从略,指定为0即可。Linux在利用socket()系统调用建立新的套接字时,需要传递套接字的地址族标识符、套接字类型以及协议,其函数定义于net/socket.c中:asmlinkagelongsys_socket(intfamily,inttype,intprotocol){intretval;structsocketsock;retval=sock_create(family,type,protocol,&sock);if(retval<0)gotoout;retval=sock_map_fd(sock);if(retval<0)gotoout_release;out:/Itmaybealreadyanotherdescriptor8)Notkernelproblem.returnretval;out_release:sock_release(sock);根据工程勘察报告揭露,本场地自地表至持力层深度范围内所揭露的土层主要由饱和粘土、砂土组成,具有成层分布的特点。页脚内容页眉内容returnretval;}实际上,套接字对于用户程序而言就是特殊的已打开的文件。内核中为套接字定义了一种特殊的文件类型,形成一种特殊的文件系统sockfs,其定义于net/socket.c:staticstructvfsmountsock_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所示。根据工程勘察报告揭露,本场地自地表至持力层深度范围内所揭露的土层主要由饱和粘土、砂土组成,具有成层分布的特点。页脚内容页眉内容实际上,socket结构与sock结构是同一事物的两个方面。如果说socket结构是面向进程和系统调用界面的,那么sock结构就是面向底层驱动程序的。可是,为什么不把这两个数据结构合并成一个呢?我们说套接字是一种特殊的文件系统,因此,inode结构内部的union的一个成分就用作socket结构,其定义如下:structinode{…union{…structsocketsocket_i;}}由于套接字操作的特殊性,这个结构中需要大量的结构成分。可是,如果把这些结构成分全都放在socket结构中,则inode结构中的这个union就会变得很大,从而inode结构也会变得很大,而对于根据工程勘察报告揭露,本场地自地表至持力层深度范围内所揭露的土层主要由饱和粘土、砂土组成,具有成层分布的特点。页脚内容页眉内容其他文件系统,这个union成分并不需要那么庞大。因此,就把套接字所需的这些结构成分拆成两部分,把与文件系统关系比较密切的那一部分放在socket结构中,把与通信关系比较密切的那一部分则单独组成一个数据结构,即sock结构。由于这两部分数据在逻辑上本来就是一体的,所以要通过指针互相指向对方,形成一对一的关系。2.在INETBSD套接字上绑定(bind)地址为了监听传入的Internet连接请求,每个服务器都需要建立一个INETBSD套接字,并且将自己的地址绑定到该套接字。绑定操作主要在INET套接字层中进行,还需要底层TCP层和IP层的某些支持。将地址绑定到某个套接字上之后,该套接字就不能用来进行任何其他的通讯,因此,该socket数据结构的状态必须为TCP_CLOSE。传递到绑定操作的sockaddr数据结构中包含要绑定的IP地址,以及一个可选的端口地址。通常而言,要绑定的地址应该是赋予某个网络设备的IP地址,而该网络设备应该支持INET地址族,并且该设备是可用的。利用ifconfig命令可查看当前活动的网络接口。被绑定的IP地址保存在sock数据结构的rcv_saddr和saddr域中,这两个域分别用于哈希查找和发送用的IP地址。端口地址是可选的,如果没有指定,底层的支持网络会选择一个空闲的端口。intbind(intsockfd,conststructsockaddrmyaddr,socklen_taddrlen);服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号。bind()成功返回0,失败返回-1。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_PORT);首先将整个结构体清零,然后设置地址类型为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_UNCONNECTED。在建立连接过程中,双方TCP要进行三次“握手”,具体过程在本章第二节——网络协议一文中有详细介绍。如果TCPsock正在等待传入消息,则该sock结构添加到tcp_listening_hash表中,这样,传入的TCP消息就可以定向到该sock数据结构。由于客户端不需要固定的端口号,因此不必调用bind(),客户端的端口号由内核自动分配。注意,客户端不是不允许调用bind(),只是没有必要调用bind()固定一个端口号,服务器也不是必须调用bind(),但如果服务器不调用bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。intconnect(intsockfd,conststructsockaddrservaddr,socklen_taddrlen);客户端需要调用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_LISTEN。当接收到某个传入的TCP连接请求时,TCP建立一个新的sock数据结构来描述该连接。当该连接最终被接受时,新的sock数据结构将变成该TCP连接的内核bottom_half部分,这时,它要克隆包含连接请求的传入sk_buff中的信息,并在监听sock数据结构的receive_queue队列中将克隆的信息排队。克隆的sk_buff中包含有指向新sock数据结构的指针。5.接受连接请求(accept)接受操作在监听套接字上进行,从监听socket中克隆一个新的socket数据结构。其过程如下:接受操作首先传递到支持协议层,即INET中,以便接受任何传入的连接请求。相反,接受操作进一步传递到实际的协议,例如TCP上。接受操作可以是阻塞的,也可以是非阻塞的。接受操作为非阻塞的情况下,如果没有可接受的传入连接,则接受操作将失败,而新建立的socket数据结构被抛弃。接受操作为阻塞的情况下,执行阻塞操作的网络应用程序将添加到等待队列中,并保持挂起直到接收到一个TCP连接请求为至。当连接请求到达之后,包含连接请求的sk_buff被丢弃,而由TCP建立的新sock数据结构返回到INET套接字层,在这里,sock数据结构和先前建立的新socket数据结构建立链接。而新socket的文件描述符(fd)被返回到网络应用程序,此后,应用程序就可以利用该文件描述符在新建立的INETBSD套接字上进行套接字操作。intaccept(intsockfd,structsockaddrcliaddr,socklen_taddrlen);三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来。cliaddr是一个传出参数,accept()返回时传出客户端的地址和端口号。addrlen参数是一个传入传出参数(value-resultargument),传入的是调用者提供的缓冲区cliaddr的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。如果给cliaddr参数传NULL,表示不关心客户端的地址。根据工程勘察报告揭露,本场地自地表至持力层深度范围内所揭露的土层主要由饱和粘土、砂土组成,具有成层分布的特点。页脚内容页眉内容注意:服务器接收到传入的请求后,如果能够接受该请求,服务器必须创建一个新的套接字来接受该请求并建立通讯连接(用于监听的套接字不能用来建立通讯连接),这时,服务器和客户就可以利用建立好的通讯连接传输数据。转载地址:http://oss.org.cn/kernel-book/ch12/12.3.4.htm根据工程勘察报告揭露,本场地自地表至持力层深度范围内所揭露的土层主要由饱和粘土、砂土组成,具有成层分布的特点。页脚内容',)
提供socket-通信过程及流程会员下载,编号:1700774251,格式为 docx,文件大小为9页,请使用软件:wps,office word 进行编辑,PPT模板中文字,图片,动画效果均可修改,PPT模板下载后图片无水印,更多精品PPT素材下载尽在某某PPT网。所有作品均是用户自行上传分享并拥有版权或使用权,仅供网友学习交流,未经上传用户书面授权,请勿作他用。若您的权利被侵害,请联系963098962@qq.com进行删除处理。