UNIX的网络通信初步.ppt
《UNIX的网络通信初步.ppt》由会员分享,可在线阅读,更多相关《UNIX的网络通信初步.ppt(107页珍藏版)》请在三一办公上搜索。
1、第六章 UNIX的网络通信初步,(1)UNIX操作系统为进程通信提供了相应设施,如管道(pipe)、命名管道(named pipe)和软中断信号(signal),消息(message)、共享存储区(shared memory)和信号量(semaphore)等,但这些都只限于用在本机进程间的通信。(2)为了实现计算机全面联网与信息的异地处理,需要为用户构建Client/Server 应用的通讯结构,通过网络接口编程,以解决不同主机进程间的通信问题。,6.1 网络接口,在UNIX系统中,网络接口有两类:一类是源自BSD UNIX的Sockets(套接口),另一类是UNIX System V 的TL
2、I(Transmission Layer Interface)。TLI是根据工业标准“ISO传输服务定义(ISO 8072)”实现的,由于SVR3只包括了流以及TLI构建模块而并没有任何的如TCP/IP之类的协议,因此TLI具有与协议无关性,关键技术是定义了一组对许多传输协议公共的服务。目前TLI的修正版XTL在UNIX系统中仍然得到广泛的使用。Socket API是基于各种传输协议之上的,目前已经成为网络编程的既成事实标准。基于Sockets API的通用性,本章只讨论Sockets API的应用。,目前最通用的提供远程进程间通信的API是伯克利套接字(Berkeley socket)接口。
3、所谓的套接字是一种抽象数据结构,用以创建一条在没有相关联的进程间发送、接收消息的通道(连接点)。这些进程在通信前各自建立一个Socket,并通过对Socket的读写操作实现通信功能。当使用基于套接字的连接时,服务器端进程创建一个套接字,并把它映射到一个本地地址上,然后等待(监听)客户端的请求。客户端进程也创建自己的套接字,并确定服务器端的具体位置(比如主机名,端口号等)。依靠传输连接方式的应答,客户端进程就可以开始发送和接收数据,而不用管是否接收到服务器进程的正式确认(应答)。,每个套接字都有其类型和一个与之相连的进程。当应用程序创建套接字时,套接字系统调用返回句柄,即所谓套接字描述字,它和文
4、件描述字是有所区别的:当文件描述字,由open命令创建时,它被耦合到特定的文件或设备;当套接字描述字由Socket命令创建时,它并不被耦合到任何位置。当套接字用作面向连接的网络传输接口时,应用程序可用bind命令将套接字明确地耦合到一个地址。当套接字用作无连接的网络传输接口时,应用程序可以在用sendto命令发送数据报时动态地提供地址。,6.1.1 套接口的类型,UNIX 提供下列四种类型的socket:数据流套接字(SOCK_STREAM),它提供双向的、面向连接的、可靠的、有序的并且不重复的无记录边界数据流。一对相连的流Socket提供几乎类似于管道的接口。流式socket针对于TCP服务
5、应用,如文件传送协议(FTP)。数据流套接字采用TCP协议,这是个有连接的协议,在数据正式传输前必须建立连接,此连接是个稳定的双向线路,可以保证提供无错误的传送管道,因为只要封包在传送过程发生错误损毁、次序错乱或送错,TCP将会察觉问题并要求重新发送数据,因此适合在需要大量的数据传输并要求完全正确的状况时使用。,6.1.1 套接口的类型,数据报套接字(SOCK_DGRAM),它也支持双向数据流,但数据以独立包形式被发送,无可靠性保证、无序、数据可能丢失或重复。数据报socket提供一个无连接服务,对应于无连接的UDP服务应用,如网络文件系统(NFS)、组播通信。数据报套接字采用UDP协议,这是
6、个无连接的协议,发送主机直接将封包送至目的主机,无需事先建立连接。因为避免了建立连接所需的高代价,采用数据报方式效率较高,但数据报方式自身不能处理数据传输过程出现的错误,因此使用数据报方式的应用程序必须自己处理这些问题。一般在比较简单的网络应用程序中使用数据报方式。,6.1.1 套接口的类型,原始套接字(SOCK_RAW),它提供对支持socket概念的基本通信协议的访问。该接口允许用户访问支持套接字抽象的底层通信协议,如IP、ICMP直接访问,常用于检验新的协议实现或访问现有服务中配置的新设备。顺序报套接字:这种类型的套接字类似数据流套接字,不同的是其传送的数据具有记录边界。,6.1.2 套
7、接口支持的协议,1套接字协议簇(family)(1)AF-UNIX:UNIX Domain协议,在该域中创建的套接字只能为同在一个主机的进程所用;(2)AF-INET:Internet协议,这个域里的套接字允许在不同主机上的不相关的进程间进行通讯;2套接字协议(Protocol)(1)TCP协议(传输控制协议):负责保证两台主机之间传输的分组到达目的地,保证分组以正确的顺序(确切的说,分组按正确的顺序重新编排)并无差错地到达目的地。当分组在两台主机间的路径上丢失时,TCP协议确保重传丢失的分组;(2)UDP协议(用户数据报协议):类似TCP协议,但是它是不可靠的。UDP不对分组进行检查、重新排
8、序和重传;,6.1.2 套接口支持的协议,6.1.3 套接口地址结构,大多数套接口函数都需要一个指向套接口地址结构的指针作参数,而在实际应用中各协议的地址结构是不同的,例如IPv4是32位的,而IPv6则是128的。由于早期定义的原因,UNIX的系统函数都只支持通用的地址结构而无法区分特定协议的地址结构,因此在调用这些函数时必须将指向具体协议的套接口地址结构的指针类型转换成指向通用套接口地址结构的类型。如serv是IPv4的地址格式,可以通过(struct sockaddr*)&serv来转换成通用地址格式。,通用套接口地址结构:(在头文件中定义)structsockaddr u_char s
9、a_len;/*地址总长度*/u_shortsa_family;/*协议族,AF_xxx*/charsa_data14;/*具体协议地址*/;其中:sa_family为套接字协议簇类型;sa_data中存储具体的协议地址,不同的协议簇有不同的地址结构,如TCP/IP协议的套接字地址结构是在文件中定义的sockaddr_in结构,这个结构定义如下:,IPv4套接口地址结构:(在头文件中定义)structsockaddr u_char sin_len;/*32位的IPv4地址总长度*/u_shortsin_family;/*协议族,AF_INET*/u_shortsin_port;/*协议端口号*
10、/charsin_zero8;/*保留,置0*/;要注意的是,套接口的地址结构是按网络字节顺序而不是按主机存储字节顺序来存储的(网络字节是从高到低的顺序,而主机是从低到高的顺序),因此,在Internet上传输数据时就需要进行转换,否则就会出现数据不一致。下面是几个常用的字节顺序转换函数:htonl():把32位值从主机字节序转换成网络字节序 ntohl():把32位值从网络字节序转换成主机字节序,通用套接口地址结构 IPv4套接口地址结构,长度 AF_INIET16位端口号 sin_portsin_zero8,长度 AF_INIET16位端口号 sin_portsa_data16,6.2 网
11、络通信的系统函数,6.2.1 建立网络连接的数据结构 一个用户为了执行网络I/O操作,它首先要调用函数socket()。这个函数陷入内核后执行sys_socket()系统调用,后者为用户创建一个名为socket的数据结构,并对其进行一些简单的初始化工作,然后返回一个小的正整数,代表这个socket结构。这个小的正整数与文件描述符功能类似,所以把它称作套接字描述符。,6.2.1 建立网络连接的数据结构,struct socket socket_state state;unsigned long flags;struct proto_ops*ops;struct inode*inode;struc
12、t fasync_struct*fasync_list;struct file*file;struct spck*sk;wait_queue_head_t wait;short type;unsigned char passcred;unsigned char tli;其中:state描述该套接字的状态信息;flags表示连接时的一些控制信息;ops指向oroto_ops 结构类型的指针;inode是指向inode 结构类型的指针;fasync_list存在异步进行处理的不同文件的指针;sk指向socket结构的指针;wait表示等待在该socket 结构上的人物列表;type表示数据包的类型
13、。,6.2.2 网络连接的建立和关闭,1 建立一个套接字描述符 函数格式如下:int socket(int family,int type,int protocol);socket()调用中有三个参数,第一个参数family是一个整数型的量,指定协议簇;第二个参数是type,表示套接字的类型;第三个参数protocol用来表示在指定协议族中使用哪种特定协议,大多情况下,该参数被设为0,让系统自己去选择基于协议族的协议。Socket()调用成功则返回一个正整数,即套接字描述符,用以标识该套接字;如果调用失败,会返回1,并设置全局变量errno为相应的错误类型。,Sockek()函数的执行流程,S
14、ocket(),Sys_socketcall(),Sys_socket(),Socket_create(),Socket_alloc(),Inet_creat(),Sk_alloc(),Sock_alloc()用来创建一个socket 结构,Sk_alloc()用来创建一个sock 结构,系统调用接口,Sock_create(.)sock_alloc();inet_creat();,例1:创建一个套接字对#include#include#include#include#include main(void)int sock2,cpid,i;/*套接字对*/static char bufBUF_S
15、Z;/*消息的临时缓冲区*/if(socketpair(PF_UNIX,SOCK_TREAM,0,sock)0)perror(“Generation error”);exit(1);switch(cpid=(int)fork()case-1:perror(“Back fork”);exit(2);case 0:/*子进程*/close(sock1);for(i=0;i 10;i+=2)sleep(1);sprintf(buf,“c:%dn”,i);write(sock0,buf,sizeof(buf);read(sock0,buf,BUF_SZ);printf(“c%s”,buf);close
16、(sock0);break;,default:/*父进程*/close(sock0);for(i=0;i 10;i+=2)sleep(1);read(sock1,buf,BUF_SZ);printf(“p%s”,buf);sprintf(buf,“p:%dn”,i);write(sock1,buf,sizeof(buf);close(sock1);return 0;,6.2.2 网络连接的建立和关闭,2 指定本机地址及端口 bind()intbind(int sockfd,structsockaddr*my_addr,int addrlen);/*0成功;-1出错*/其中:参数sockfd是调
17、用socket()返回的套接字,参数my_addr是通用地址结构指针,参数addrlen是该结构的长度,常被设置为sizeof(structsockaddr)。该函数为套接字分配一个本地协议地址,对于IP协议来说是IP地址和TCP或UDP端口号的组合。bind()调用在UNIX域中用来联系套接字和它的名字(一个文件名),在因特网域用来将本地地址和套接字绑定在一起,包括IP地址和端口号。它是依据第二个参数的值的不同而不同的;套接字和本地地址的绑定采用组合的方式,如下表,注:INADDR-ANY在UNIX系统中被映射为0的常量,6.2.2 网络连接的建立与关闭,使用bind函数时,可以用下面的赋值
18、实现自动获得本机IP地址和随机获取一个没有被占用的端口号:my_addr.sin_port=0;/*系统随机选择一个未被使用的端口号*/my_addr.sin_addr.s_addr=INADDR_ANY;/*填入本机IP地址*/,6.2.2 网络连接的建立与关闭,3 客户启动连接connect()intconnect(intsockfd,structsockaddr*serv_addr,intaddrlen);/*返回:0成功;-1出错*/sockfd是调用socket()返回的套接字;serv_addr是包含远端服务器IP地址和端口号的通用地址结构的指针;addrlen是远端地址结构的长度
19、。TCP客户用Connect函数建立一个与远端TCP服务器的连接,正是connect激发了TCP三次握手的连接过程。由于协议族总被包含在套接字地址结构的前两个字节中,并通过socket()调用与某个协议族相关。因此bind()和connect()无须协议作为参数。,connect(),用户空间,核心空间,sys_socketcall(),sys_connect(),inet_stream_coonect(),tcp_v4_connect(),ip_route_output(),ip_route_output_key(),ip_route_connect(),ip_output(),ip_rou
20、te_optput_slow(),系统调用,传输层(TCP协议),网络层(IPv4或IPv6),6.2.2 网络连接的建立与关闭,4 监听连接listen()intlisten(intsockfd,intbacklog);/*返回:0成功;-1出错*/sockfd是调用socket()建立的套接字,它是一个socket调用成功后的返回值;backlog是指定在请求队列中允许的最大请求数,一般大于5的均设为5。进入的连接请求将在队列中等待accept()调用建立与客户的连接。该函数仅被TCP服务器调用,它总是使套接口处于被动的监听模式,并为该套接口建立一个输入数据队列,将到达的服务请求保存在此队
21、列中,直到程序处理它们。如果一个服务请求到来时,输入队列已满,该套接口将拒绝连接请求并显示出错信息。listen()调用将一个尚未连接的主动套接字转换成为一个被动套接字,使其可以接收连接请求,因为由socket()调用所创建的套接字(主动套接字)只可以用来进行主动连接,不能接收连接的请求。,5 服务器接受连接accept()intaccept(intsockfd,structsockaddr*addr,int*addrlen);/*返回:0成功;-1出错*/accept()调用从倾听套接字的连接队列中接收第一个连接,生成一个新的套接字来完成客户机的要求,原来的套接字继续监视网络,等待用户的连接
22、。accept()调用的第一个参数sockfd是用来标识从哪个套接字中接收连接的,addr是一个指向客户方套接字地址结构的变量指针,该变量用来接收提出连接请求服务的客户的协议地址,指明某台主机从某个端口发出该请求;addr的确切格式由套接字创建时建立的地址族决定。addrten通常为一个指向值为sizeof(struct socka ddr)的整型指针变量,指明客户方套接字地址结构的长度(字节数)。accept()只用于TCP服务器,且在调用前应该先调用过listen()。当listen()侦听到有连接请求到达时,accept()调用将请求连接队列上的第一个客户的套接字地址及长度放入addr和
23、addrlen,并与该客户在sockfd建立连接。,6.2.2 网络连接的建立与关闭,6 关闭套接字close()close(intsockfd);参数sockfd是待关闭的套接字。close()是标准的关闭函数,在TCP服务中激发该套接字的连接关闭。函数功能只是对该套接字作“关闭标识”表明不可用,而连接的另一方还在试图发送排队的数据。只有当对方发现通信的套接字已不可用,自己也调用close()关闭本机的套接字,才真正地结束数据的发送。,6.2.3 发送数据,UNIX内核为用户提供的发送数据的系统调用有5个,它们分别是:1)write():与文件系统中的write()完全一致;2)writev
24、():与write功能相似,所不同的是writev可以在一次函数调用中写多个缓冲区(集中写)3)send():面向连接的发送数据过程(TCP);4)sendto():面向无连接的发送数据过程(UDP)5)sendmsg():直接使用msghdr 结构发送数据。在功能上可以代替以上四个输出函数。,1 发送数据的系统调用接口,write(),writev(),send(),sendto(),sendmsg(),sys_write(),sys_writev(),sys_socketcall(),sock_write(),sock_write(),sys_send(),sys_sendmsg(),sy
25、s_sendto(),sock_sendmsg(),inet_sendmsg(),系统调用,应用层,BSD 套接字接口,INET 套接字(传输层),2.从INTE协议层到IP层,inet_sendmsg(),tcp_sendmsg(),tcp_sendmsg()tcp_transmit_skb(),ip_queue_xmit(),网络层,BSD 套接字接口,INET 套接字(传输层),2.IP层到硬件层的数据发送过程,ip_queue_xmit2(),ip_output(),ip_finish_output(),ip_queue_xmit(),net/core/dev.c,IP层,dev_qu
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- UNIX 网络 通信 初步
链接地址:https://www.31ppt.com/p-6522532.html