【asp精品源码栏目提醒】:以下是网学会员为您推荐的asp精品源码-socket的通信过程 - 其它资料,希望本篇文章对您学习有所帮助。
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则连接处于半关闭状态,仍可接收对方发来的数据。
在学习 socket API 时要注意应用程序和 TCP 协议层是如何交互的: 应用程序调用某个socket 函数时 TCP 协议层完成什么动作,比如调用 connect会发出 SYN 段 应用程序如何知道 TCP 协议层的状态变化, 比如从某个阻塞的 socket 函数返回就表明 TCP 协议收到了某些段,再比如 read返回 0 就表明收到了 FIN 段看图所示的socket 通信过程图 12.9 socket 的通信过程1.建立套接字在 sys/socket.h 中。
int socketint family int type int protocolsocket打开一个网络通讯端口,如果成功的话,就像 open一样返回一个文件描述符,应用程序可以像读写文件一样用 read/write 在网络上收发数据,如果 socket调用出错则返回-1。
对于 IPv4,family 参数指定为 AF_INET。
对于 TCP 协议,type 参数指定为SOCK_STREAM,表示面向流的传输协议。
如果是 UDP 协议,则 type 参数指定为SOCK_DGRAM,表示面向数据报的传输协议。
protocol 参数的介绍从略,指定为 0 即可。
Linux 在利用 socket系统调用建立新的套接字时,需要传递套接字的地址族标识符、套接字类型以及协议其函数定义于 net/socket.c 中: asmlinkagelong sys_socketint family int type int protocol int retval struct socket sock retval sock_createfamily type protocolsock if retval 0 goto out retval sock_map_fdsock if retval 0 goto out_releaseout: / It may be already another descriptor 8 Not kernel problem. / return retvalout_release: sock_releasesock return retval 实际上,套接字对于用户程序而言就是特殊的已打开的文件。
内核中为套接字定义了一种特殊的文件类型,形成一种特殊的文件系统 sockfs,其定义于 net/socket.c:static struct vfsmount sock_mntstatic DECLARE_FSTYPEsock_fs_type sockfssockfs_read_superFS_NOMOUNT 在系统初始化时,要通过 kern_mount安装这个文件系统。
安装时有个作为连接件的vfsmount 数据结构,这个结构的地址就保存在一个全局的指针 sock_mnt 中。
所谓创建一个套接字,就是在 sockfs 文件系统中创建一个特殊文件,或者说一个节点,并建立起为实现套接字功能所需的一整套数据结构。
所以,函数 sock_create首先是建立一个 socket数据结构,然后将其“映射”到一个已打开的文件中,进行 socket 结构和 sock 结构的分配和初始化。
新创建的 BSD socket 数据结构包含有指向地址族专有的套接字例程的指针,这一指针实际就是 proto_ops 数据结构的地址。
BSD 套接字的套接字类型设置为所请求的 SOCK_STREAM 或 SOCK_DGRAM 等 。
然后,内核利用 proto_ops 数据结构中的信息调用地址族专有的创建例程。
之后,内核从当前进程的 fd 向量中分配空闲的文件描述符,该描述符指向的 file 数据结构被初始化。
初始化过程包括将文件操作集指针指向由 BSD 套接字接口支持的 BSD 文件操作集。
所有随后的套接字(文件)操作都将定向到该套接字接口,而套接字接口则会进一步调用地址族的操作例程,从而将操作传递到底层地址族如图 12.10 所示。
实际上,socket 结构与 sock 结构是同一事物的两个方面。
如果说 socket 结构是面向进程和系统调用界面的,那么 sock 结构就是面向底层驱动程序的。
可是,为什么不把这两个数据结构合并成一个呢?我们说套接字是一种特殊的文件系统,因此,inode 结构内部的 union 的一个成分就用作socket 结构,其定义如下:struct inode { … union … struct socket socket_i 由于套接字操作的特殊性,这个结构中需要大量的结构成分。
可是,如果把这些结构成分全都放在 socket 结构中,则 inode 结构中的这个 union 就会变得很大,从而 inode 结构也会变得很大,而对于其他文件系统,这个 union 成分并不需要那么庞大。
因此,就把套接字所需的这些结构成分拆成两部分,把与文件系统关系比较密切的那一部分放在 socket结构中,把与通信关系比较密切的那一部分则单独组成一个数据结构,即 sock 结构。
由于这两部分数据在逻辑上本来就是一体的,所以要通过指针互相指向对方,形成一对一的关系。
2.在 INET BSD 套接字上绑定(bind)地址为了监听传入的 Internet 连接请求,每个服务器都需要建立一个 INET BSD 套接字,并且将自己的地址绑定到该套接字。
绑定操作主要在 INET 套接字层中进行,还需要底层TCP 层和 IP 层的某些支持。
将地址绑定到某个套接字上之后,该套接字就不能用来进行任何其他的通讯,因此,该 socket 数据结构的状态必须为 TCP_CLOSE。
传递到绑定操作的 sockaddr 数据结构中包含要绑定的 IP 地址,以及一个可选的端口地址。
通常而言,要绑定的地址应该是赋予某个网络设备的 IP 地址,而该网络设备应该支持 INET 地址族,并且该设备是可用的。
利用 ifconfig 命令可查看当前活动的网络接口。
被绑定的 IP地址保存在 sock 数据结构的 rcv_saddr 和 saddr 域中,这两个域分别用于哈希查找和发送用的 IP 地址。
端口地址是可选的,如果没有指定,底层的支持网络会选择一个空闲的端口。
int bindint sockfd const struct sockaddr myaddr socklen_t addrlen服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用 bind 绑定一个固定的网络地址和端口号。
bind成功返回 0,失败返回-1。
使bind的作用是将参数 sockfd 和 myaddr 绑定在一起, sockfd 这个用于网络通讯的文件描述符监听 myaddr 所描述的地址和端口号。
前面讲过,struct sockaddr 是一个通用指针 myaddr 参数实际上可以接受多种协议的 sockaddr 结构体,类型, 而它们的长度各不相同,所以需要第三个参数 addrlen 指定结构体的长度。
我们的程序中对 myaddr 参数是这样初始化的: bzeroservaddr sizeofservaddr servaddr.s
上一篇:
平顶山学院教案
下一篇:
问卷调查可以自动生成试卷等,并且只能一个用户登录