《《linux套接字编程》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《linux套接字编程》PPT课件.ppt(44页珍藏版)》请在金锄头文库上搜索。
1、第三章第三章 套接字套接字套接字是一种网络套接字是一种网络套接字是一种网络套接字是一种网络APIAPI(应用程序编程接口)。(应用程序编程接口)。(应用程序编程接口)。(应用程序编程接口)。它定义了许多函数和例程,程序员可以用它开发它定义了许多函数和例程,程序员可以用它开发它定义了许多函数和例程,程序员可以用它开发它定义了许多函数和例程,程序员可以用它开发网络应用程序。套接字接口本意在于提供一种进网络应用程序。套接字接口本意在于提供一种进网络应用程序。套接字接口本意在于提供一种进网络应用程序。套接字接口本意在于提供一种进程间通信的方法,使得在相同或不同主机上的进程间通信的方法,使得在相同或不同
2、主机上的进程间通信的方法,使得在相同或不同主机上的进程间通信的方法,使得在相同或不同主机上的进程能以相同的规范进行双向信息传送。程能以相同的规范进行双向信息传送。程能以相同的规范进行双向信息传送。程能以相同的规范进行双向信息传送。进程通过调用进程通过调用进程通过调用进程通过调用套接字接口套接字接口套接字接口套接字接口APIAPI来实现相互之间的来实现相互之间的来实现相互之间的来实现相互之间的通信。套接字接口又利用下层的网络通信协议功通信。套接字接口又利用下层的网络通信协议功通信。套接字接口又利用下层的网络通信协议功通信。套接字接口又利用下层的网络通信协议功能和系统调用实现实际的通信工作。能和系
3、统调用实现实际的通信工作。能和系统调用实现实际的通信工作。能和系统调用实现实际的通信工作。 进程通信与套接字接口进程通信与套接字接口进程通信与套接字接口进程通信与套接字接口2processTCP withbuffers,variablessocket由应用程序由应用程序开发者控制开发者控制由操作系统控制由操作系统控制host orserverprocessTCP withbuffers,variablessocketcontrolled byapplicationdevelopercontrolled byoperatingsystemhost orserverinternet1. 套接字是一
4、个主机本地应用程序所创建的套接字是一个主机本地应用程序所创建的, 为操作系为操作系统所控制的接口统所控制的接口 (“门门”) .2. 应用进程通过这个接口应用进程通过这个接口,使用传输层提供的服务使用传输层提供的服务, 跨网跨网络发送络发送(/接收接收)消息到消息到(/从从)其他应用进程。其他应用进程。3.Client/server模式的通信接口模式的通信接口套接字接口套接字接口.3本章内容本章内容3.1 套接字类型套接字类型3.2 套接字地址结构套接字地址结构3.3 位顺序调整位顺序调整3.4 带外数据带外数据3.5 连接类型连接类型3.6 TCP套接字套接字3.7 UDP套接字套接字3.8
5、 小结小结43.1 套接字类型套接字类型套接字支持各种通信域,即多种不同的通信协套接字支持各种通信域,即多种不同的通信协议。目前议。目前UNIX系统主要支持以下几种协议:系统主要支持以下几种协议:UNIXUNIX:UNIXUNIX系统内部协议系统内部协议系统内部协议系统内部协议INET: IPINET: IP版本版本版本版本4 4INET6: IPINET6: IP版本版本版本版本6 65UNIXUNIX系统支持多种套接字类型。系统支持多种套接字类型。系统支持多种套接字类型。系统支持多种套接字类型。套接字类型:是指创建套套接字类型:是指创建套套接字类型:是指创建套套接字类型:是指创建套接字的应
6、用程序所希望的通信服务类型。接字的应用程序所希望的通信服务类型。接字的应用程序所希望的通信服务类型。接字的应用程序所希望的通信服务类型。目前,目前,目前,目前,UNIXUNIX系统系统系统系统主要定义如下:主要定义如下:主要定义如下:主要定义如下: SOCK_STREAM:SOCK_STREAM:提供可靠的面向连接传输的数据流,保证数据在传提供可靠的面向连接传输的数据流,保证数据在传输过程中无丢失、无损坏和无冗余。输过程中无丢失、无损坏和无冗余。INETINET地址簇中的地址簇中的TCPTCP协议支持该协议支持该套接字。套接字。 SOCK_DGRAM:SOCK_DGRAM:提供数据的双向传输,
7、但不保证消息地准确到达,即提供数据的双向传输,但不保证消息地准确到达,即使消息能够到达,也无法保证其顺序性,并可能有冗余或损坏。使消息能够到达,也无法保证其顺序性,并可能有冗余或损坏。INETINET地址簇中的地址簇中的UDPUDP协议支持该套接字。协议支持该套接字。 SOCK_RAM:SOCK_RAM:是低于传输层的低级协议或物理网络提供的套接字类型。是低于传输层的低级协议或物理网络提供的套接字类型。它可以访问内部网络接口。例如,可以接收和发送它可以访问内部网络接口。例如,可以接收和发送ICMPICMP报。报。 SOCK_SEQPACKET:SOCK_SEQPACKET:提供可靠的、双向的、
8、顺序化的以及面向连接提供可靠的、双向的、顺序化的以及面向连接的数据通信。类似于的数据通信。类似于STREAMSTREAM方式,但它的报文大小可变(最大报文方式,但它的报文大小可变(最大报文长度固定)。长度固定)。 SOCK_RDM:SOCK_RDM:类似于类似于SOCK_DGRAMSOCK_DGRAM,但它可保证数据的正确到达。,但它可保证数据的正确到达。63.2 套接字地址结构套接字地址结构多数套接字函数需要一个指向地址结构的参数。多数套接字函数需要一个指向地址结构的参数。对应于不同的协议簇,有不同的地址结构。在头对应于不同的协议簇,有不同的地址结构。在头文件文件中定义了以下结构来保持中定义
9、了以下结构来保持套接字函数调用参数的一致性。套接字函数调用参数的一致性。struct sockaddrstruct sockaddr unsigned short sa_family; unsigned short sa_family; /* /* 地址类型,格式为地址类型,格式为AF_XXX */AF_XXX */ char sa_data14; char sa_data14; /* 14/* 14字节的协议地址字节的协议地址 * */ / ;其中的其中的其中的其中的sa_familysa_family为套接字的协议簇地址类型,为套接字的协议簇地址类型,为套接字的协议簇地址类型,为套接字的协
10、议簇地址类型,TCP/IPTCP/IP的协议对的协议对的协议对的协议对于于于于IPv4IPv4地址类型为地址类型为地址类型为地址类型为AF_INETAF_INET。sa_datasa_data中存储具体的协议地址,中存储具体的协议地址,中存储具体的协议地址,中存储具体的协议地址,不同的协议簇有不同的地址格式。不同的协议簇有不同的地址格式。不同的协议簇有不同的地址格式。不同的协议簇有不同的地址格式。7但一般编程中并不直接针对此数据结构操作,而是使但一般编程中并不直接针对此数据结构操作,而是使但一般编程中并不直接针对此数据结构操作,而是使但一般编程中并不直接针对此数据结构操作,而是使用另一个与用另
11、一个与用另一个与用另一个与sockaddrsockaddr等价的数据结构等价的数据结构等价的数据结构等价的数据结构sockaddr_in (sockaddr_in (在在在在netinet/in.hnetinet/in.h中定义中定义中定义中定义) ):struct sockaddr_instruct sockaddr_in unsigned short int sin_len; unsigned short int sin_len; /* IPv4/* IPv4地址长度地址长度地址长度地址长度 * */ / short int sin_family; short int sin_family
12、; /* /* 地址类型地址类型地址类型地址类型 * */ / unsigned short int sin_port; unsigned short int sin_port; /* /* 存储端口号存储端口号存储端口号存储端口号 * */ / struct in_addr sin_addr; struct in_addr sin_addr; /*/*存储存储存储存储IPIP地址地址地址地址 * */ / unsigned char sin_zero8; unsigned char sin_zero8; /* /* 空字节空字节空字节空字节 * */ / ;在编程中大多数是使用在编程中大多数
13、是使用在编程中大多数是使用在编程中大多数是使用sockaddr_insockaddr_in这个结构来设置这个结构来设置这个结构来设置这个结构来设置/ /获取地址信息。获取地址信息。获取地址信息。获取地址信息。sin_familysin_family指代协议族,在指代协议族,在指代协议族,在指代协议族,在TCPTCP套接字编程中只能是套接字编程中只能是套接字编程中只能是套接字编程中只能是AF_INET;AF_INET;sin_portsin_port存储端口号(使用网络字节顺序),数据类型是一个存储端口号(使用网络字节顺序),数据类型是一个存储端口号(使用网络字节顺序),数据类型是一个存储端口号
14、(使用网络字节顺序),数据类型是一个1616位的无符号整数类型;位的无符号整数类型;位的无符号整数类型;位的无符号整数类型;sin_addrsin_addr存储存储IPIP地址,地址,IPIP地址使用地址使用in_addrin_addr这个数据结构:这个数据结构: struct in_addr unsigned long s_addr; ;struct in_addr unsigned long s_addr; ;这个数据结构是由于历史原因保留下来,主要用作与以前的格式兼容。这里这个数据结构是由于历史原因保留下来,主要用作与以前的格式兼容。这里的的s_addrs_addr按照网络字节顺序存储按
15、照网络字节顺序存储IPIP地址。地址。sin_zerosin_zero是为了让是为了让是为了让是为了让sockaddrsockaddr与与与与sockaddr_insockaddr_in两个数据结构保持两个数据结构保持两个数据结构保持两个数据结构保持大小相同而保留的空字节。大小相同而保留的空字节。大小相同而保留的空字节。大小相同而保留的空字节。8在在在在IPv6IPv6中套接字地址结构采用另外的定义:中套接字地址结构采用另外的定义:中套接字地址结构采用另外的定义:中套接字地址结构采用另外的定义:#DEFINE SIN6_LEN #DEFINE SIN6_LEN /* /* 如果系统支持套接字地
16、址结构中的长度成员,如果系统支持套接字地址结构中的长度成员,则此常值必须定义则此常值必须定义* */ /struct sockaddr_in6struct sockaddr_in6 unsigned short int sin6_len; unsigned short int sin6_len; /*IPv6/*IPv6结构体长度结构体长度 * */ / short int sin6_family; short int sin6_family; /*/*地址类型地址类型 * */ / unsigned short int sin6_port; unsigned short int sin6_p
17、ort; /*/*存储端口号,网络字节顺序存储端口号,网络字节顺序* */ / unsigned short int sin6_flowinfo; unsigned short int sin6_flowinfo; /*/*优先级和流量标志,网络字优先级和流量标志,网络字节顺序节顺序 * */ / struct in6_addr sin6_addr; struct in6_addr sin6_addr; /*IPv6/*IPv6地址,网络字节顺序地址,网络字节顺序* */ / ;struct in6_addrstruct in6_addr unsigned long s6_addr; unsi
18、gned long s6_addr; /*128/*128位位IPv6IPv6地址,网络字节顺序地址,网络字节顺序* */ / ;其中其中sin6_lensin6_len是一个无符号的是一个无符号的8 8位整数,表示位整数,表示128128位位IPv6IPv6地址长度;地址长度;sin6_familysin6_family是是IPv6IPv6的地址类型;结构中的成员是有序排列的,都是的地址类型;结构中的成员是有序排列的,都是6464位对齐的;位对齐的;sin6_flowinfosin6_flowinfo的的结构是:低结构是:低2424位是流量标号,然后位是流量标号,然后4 4位的优先级标志,剩
19、下位的优先级标志,剩下4 4位保留。位保留。9比较比较比较比较IPv4IPv4和和和和IPv6IPv6的地址结构的地址结构的地址结构的地址结构长度AF_INET16位端口号32位IPv4地址sin_zero未用长度AF_INET616位端口号32位流量标志128位IPv6地址 IPv4IPv4地址解构的固定长度是地址解构的固定长度是地址解构的固定长度是地址解构的固定长度是1616字节,而字节,而字节,而字节,而IPv6IPv6的地址结构的的地址结构的的地址结构的的地址结构的固定长度是固定长度是固定长度是固定长度是2424字节。字节。字节。字节。10设置地址信息的实例(设置地址信息的实例(IPv
20、4)struct sockaddr_in mysock;struct sockaddr_in mysock; /* /*设置设置设置设置sockaddr_insockaddr_in的结的结的结的结构体变量构体变量构体变量构体变量mysock */mysock */mysock.sin_family=AF_INET; mysock.sin_family=AF_INET; /*TCP/*TCP地址结构地址结构地址结构地址结构* */ /mysock.sin_port=htons(3490); mysock.sin_port=htons(3490); /*short,NBO*/*short,NBO*
21、/mysock.sin_addr.s_addr=inet_addr(“192.168.1.22mysock.sin_addr.s_addr=inet_addr(“192.168.1.221”); 1”); /*/*设置地址为设置地址为设置地址为设置地址为192.168.1.221*/192.168.1.221*/bzero(&(mysock.sin_zero),8); bzero(&(mysock.sin_zero),8); /*/*设置设置设置设置sin_zerosin_zero为为为为8 8位位位位保留字节保留字节保留字节保留字节* */ /注意:注意:注意:注意:如果如果如果如果myso
22、ck.sin_addr.s_addr=INADDR_ANY,mysock.sin_addr.s_addr=INADDR_ANY,则不指则不指则不指则不指定定定定IPIP地址(用于地址(用于地址(用于地址(用于serverserver程序)。程序)。程序)。程序)。113.2.1 IP地址转换函数地址转换函数unsigned long inet_addr(const char *cp);unsigned long inet_addr(const char *cp);inet_addrinet_addr将一个点分十进制将一个点分十进制将一个点分十进制将一个点分十进制IPIP地址字符串转换成地址字符
23、串转换成地址字符串转换成地址字符串转换成3232位数字位数字位数字位数字表示的表示的表示的表示的IPIP地址(网络字节顺序)。地址(网络字节顺序)。地址(网络字节顺序)。地址(网络字节顺序)。char *inet_ntoa(struct in_addr in);char *inet_ntoa(struct in_addr in);inet_ntoainet_ntoa将一个将一个将一个将一个3232位数字表示的位数字表示的位数字表示的位数字表示的IPIP地址转换成点分十进制地址转换成点分十进制地址转换成点分十进制地址转换成点分十进制IPIP地址字符串。地址字符串。地址字符串。地址字符串。这两个函
24、数互为反函数。这两个函数互为反函数。这两个函数互为反函数。这两个函数互为反函数。123.2.2 3.2.2 套接字地址结构与内核之间的传递套接字地址结构与内核之间的传递套接字地址结构与内核之间的传递套接字地址结构与内核之间的传递当把套接字地址结构传递给套接字处理函数时,是当把套接字地址结构传递给套接字处理函数时,是当把套接字地址结构传递给套接字处理函数时,是当把套接字地址结构传递给套接字处理函数时,是通过指向结构的指针来传递的。结构的长度也作为通过指向结构的指针来传递的。结构的长度也作为通过指向结构的指针来传递的。结构的长度也作为通过指向结构的指针来传递的。结构的长度也作为参数来传递,其传递的
25、方向可以是从进程到内核,参数来传递,其传递的方向可以是从进程到内核,参数来传递,其传递的方向可以是从进程到内核,参数来传递,其传递的方向可以是从进程到内核,也可以是从内核到进程。也可以是从内核到进程。也可以是从内核到进程。也可以是从内核到进程。长度长度长度长度内核内核内核内核套接字地址结构套接字地址结构协议地址协议地址协议地址协议地址13从进程到内核传递套接字地址结构从进程到内核传递套接字地址结构 由于指针所指结构的大小都传递给内核,所以从进程到内核的数据拷由于指针所指结构的大小都传递给内核,所以从进程到内核的数据拷贝量使知道的。进行这样操作的一般有这贝量使知道的。进行这样操作的一般有这3 3
26、个函数:个函数:bind,connectbind,connect和和sendto,sendto,它们的一个参数是指向套接字地址结构的指针,另一个参数是它们的一个参数是指向套接字地址结构的指针,另一个参数是结构的大小(结构的大小(intint)。)。从内核到进程传递套接字地址结构从内核到进程传递套接字地址结构 这里主要用到这里主要用到4 4个函数:个函数:accept,recvfrom,getsocknameaccept,recvfrom,getsockname和和getpeernamegetpeername。它们的两个参数分别是指向套接字地址结构的指针和。它们的两个参数分别是指向套接字地址结构
27、的指针和指向表示结构大小的整数的指针。注意:跟上面不同的是第二个参数指向表示结构大小的整数的指针。注意:跟上面不同的是第二个参数不再是整型(不再是整型(intint), ,而是一个整型指针(而是一个整型指针(int *int *), ,这是由于函数在调用这是由于函数在调用和返回时结构大小不同,不至于使内核在写此结构时产生越界错误而和返回时结构大小不同,不至于使内核在写此结构时产生越界错误而设置的。设置的。长度长度长度长度内核内核内核内核套接字地址结构套接字地址结构协议地址协议地址协议地址协议地址143.3 位顺序调整位顺序调整网络中存在多种类型的机器,这些不同类型的网络中存在多种类型的机器,这
28、些不同类型的机器表示数据的字节顺序是不同的。机器表示数据的字节顺序是不同的。以以以以1616进制数进制数进制数进制数308A308A,在内存地址,在内存地址,在内存地址,在内存地址0x10000x1000的存储为的存储为的存储为的存储为例例例例30308A8A30308A8A0x10000x10000x10000x10000x10010x10010x10010x1001小端字节序小端字节序小端字节序小端字节序大端字节序大端字节序大端字节序大端字节序网络协议中的数据采用统一的网络字节顺序,因为只有采用统一的字节网络协议中的数据采用统一的网络字节顺序,因为只有采用统一的字节网络协议中的数据采用统一
29、的网络字节顺序,因为只有采用统一的字节网络协议中的数据采用统一的网络字节顺序,因为只有采用统一的字节顺序,才能在不同类型的硬件设备之间正确的发送和接收数据。顺序,才能在不同类型的硬件设备之间正确的发送和接收数据。顺序,才能在不同类型的硬件设备之间正确的发送和接收数据。顺序,才能在不同类型的硬件设备之间正确的发送和接收数据。广域网广域网广域网广域网规定的网络字节顺序采用大端字节顺序方式。规定的网络字节顺序采用大端字节顺序方式。规定的网络字节顺序采用大端字节顺序方式。规定的网络字节顺序采用大端字节顺序方式。15系统提供系统提供4个函数来进行字节顺序转换:个函数来进行字节顺序转换:#include
30、“netinet/in.h”#include “netinet/in.h”unsigned short int htons(unsigned short int unsigned short int htons(unsigned short int hostshorthostshort); ); unsigned long int htonl(unsigned long int unsigned long int htonl(unsigned long int hostlonghostlong); );unsigned short int ntons(unsigned short int un
31、signed short int ntons(unsigned short int netshortnetshort); );unsigned long int ntonl(unsigned long int unsigned long int ntonl(unsigned long int netlongnetlong); );其中。前两个函数将主机字节顺序转换成网络字节顺序;后两个函数将网其中。前两个函数将主机字节顺序转换成网络字节顺序;后两个函数将网络字节顺序转换成主机字节顺序。络字节顺序转换成主机字节顺序。在使用这些函数时,我们不关心主机或网络顺序的真实值到底是大端还是在使用这些函数时
32、,我们不关心主机或网络顺序的真实值到底是大端还是小端,只需要调用适当的函数来对给定值(函数的整型参数)进行主机字小端,只需要调用适当的函数来对给定值(函数的整型参数)进行主机字节顺序和网络字节顺序的转换,它们的返回值就是经过转换以后的结果。节顺序和网络字节顺序的转换,它们的返回值就是经过转换以后的结果。163.3.1 字节处理函数字节处理函数系统提供两组函数来处理多字节数据,一组函数是系统提供两组函数来处理多字节数据,一组函数是系统提供两组函数来处理多字节数据,一组函数是系统提供两组函数来处理多字节数据,一组函数是以以以以b b(bytebyte)开头,和)开头,和)开头,和)开头,和BSDB
33、SD系统兼容的函数;另一组系统兼容的函数;另一组系统兼容的函数;另一组系统兼容的函数;另一组是以是以是以是以memmem开头,开头,开头,开头,ANSI CANSI C所提供的函数。所提供的函数。所提供的函数。所提供的函数。 BSDBSD系统兼容函数:系统兼容函数:系统兼容函数:系统兼容函数:#include #include void bzero(void *s,int n);void bzero(void *s,int n);void bcopy(const void *src,void *dest,int n);void bcopy(const void *src,void *dest,
34、int n);void bcmp(const void *s1,const void *s2,int n);void bcmp(const void *s1,const void *s2,int n); ANSI CANSI C函数:函数:函数:函数:#include #include void *memset(void *s,int c,size_t n);void *memset(void *s,int c,size_t n);void *memcopy(void *dest,const void *src,size_t n);void *memcopy(void *dest,const
35、void *src,size_t n);int memcmp(const void *s1,const void *s2, size_t n);int memcmp(const void *s1,const void *s2, size_t n);17bzerobzero函数将目标中指定数目的字节置为函数将目标中指定数目的字节置为函数将目标中指定数目的字节置为函数将目标中指定数目的字节置为0 0,这个函数经常用,这个函数经常用,这个函数经常用,这个函数经常用来把套接字地址结构初始化为来把套接字地址结构初始化为来把套接字地址结构初始化为来把套接字地址结构初始化为0 0,如:,如:,如:,如:bz
36、ero(&servaddr,sizeof(servaddr);bzero(&servaddr,sizeof(servaddr);bcopybcopy将指定数目的字节从源将指定数目的字节从源将指定数目的字节从源将指定数目的字节从源srcsrc移动到目标移动到目标移动到目标移动到目标destdest指定的内存指定的内存指定的内存指定的内存区域;区域;区域;区域;bcmpbcmp比较任意两个内存区域,即比较任意两个内存区域,即比较任意两个内存区域,即比较任意两个内存区域,即s1s1指定的内存区域与指定的内存区域与指定的内存区域与指定的内存区域与s2s2指定指定指定指定的内存区域的前的内存区域的前的内
37、存区域的前的内存区域的前n n个字节,若相同则返回值为个字节,若相同则返回值为个字节,若相同则返回值为个字节,若相同则返回值为0 0,否则返回值,否则返回值,否则返回值,否则返回值为非为非为非为非0 0;memsetmemset函数将参数函数将参数函数将参数函数将参数s s指定的内存区域的前指定的内存区域的前指定的内存区域的前指定的内存区域的前n n个字节设置为参数个字节设置为参数个字节设置为参数个字节设置为参数c c的内容;的内容;的内容;的内容;memcpymemcpy函数等同于函数等同于函数等同于函数等同于bcopybcopy,差别是,差别是,差别是,差别是bcopybcopy可以处理源
38、可以处理源可以处理源可以处理源srcsrc和目和目和目和目标标标标destdest相重叠的情况,而相重叠的情况,而相重叠的情况,而相重叠的情况,而memcpymemcpy则对这种情况没有定义。则对这种情况没有定义。则对这种情况没有定义。则对这种情况没有定义。memcmpmemcmp与与与与bcmpbcmp类似。类似。类似。类似。183.3.2 地址转换函数地址转换函数地址转换函数负责在地址转换函数负责在地址转换函数负责在地址转换函数负责在ASCIIASCII字符串和网络字节顺序的字符串和网络字节顺序的字符串和网络字节顺序的字符串和网络字节顺序的二进制值之间进行地址转换。二进制值之间进行地址转换
39、。二进制值之间进行地址转换。二进制值之间进行地址转换。inet_aton,inet_addrinet_aton,inet_addr和和和和inet_ntoainet_ntoa函数函数函数函数#include #include int inet_aton(const char *strptr,struct in_addr *addrptr);int inet_aton(const char *strptr,struct in_addr *addrptr);in_addr_t inet_addr(const char *strptr);in_addr_t inet_addr(const char
40、*strptr);char *inet_ntoa(struct in_addr inaddr);char *inet_ntoa(struct in_addr inaddr);inet_atoninet_aton函数将函数将strptrstrptr所指向的字符串转换成所指向的字符串转换成3232位的网络字节序二进制值,位的网络字节序二进制值,并存储在指针并存储在指针addrptraddrptr指向的指向的in_addrin_addr结构体中,若成功,返回结构体中,若成功,返回1 1。inet_addrinet_addr函数,其转换结果作为返回值返回函数,其转换结果作为返回值返回3232位二进制网
41、络字节序地址,位二进制网络字节序地址,若转换错,则返回若转换错,则返回INADDR_NONEINADDR_NONE。inet_ntoainet_ntoa函数将一个函数将一个3232位的网络字节序二进制位的网络字节序二进制IPv4IPv4地址转换成相应的点地址转换成相应的点分十进制数串,转换结果存于静态内存中,返回一个指向该地址的指针。分十进制数串,转换结果存于静态内存中,返回一个指向该地址的指针。19inet_pton和和inet_ntop函数函数这两个函数功能基本同上,但它们不仅可处理这两个函数功能基本同上,但它们不仅可处理这两个函数功能基本同上,但它们不仅可处理这两个函数功能基本同上,但它
42、们不仅可处理IPV4IPV4的地址,对于的地址,对于的地址,对于的地址,对于128128位的位的位的位的IPv6IPv6的地址也可以处理。的地址也可以处理。的地址也可以处理。的地址也可以处理。#include #include int inet_pton(int family,const char *strptr,void *addrptr);int inet_pton(int family,const char *strptr,void *addrptr);const char *inet_ntop(int family,const void *addrptr,char const char
43、 *inet_ntop(int family,const void *addrptr,char *strptr,size_t len);*strptr,size_t len);familyfamily即可以是即可以是AF_INET,AF_INET,也可以是也可以是AF_INET6AF_INET6。inet_ptoninet_pton指针指针strptrstrptr指向需要转换的字符串,指向需要转换的字符串,addrptraddrptr用来存储转换结果。而用来存储转换结果。而inet_ntopinet_ntop进行进行相反的转换,从二进制的数值(相反的转换,从二进制的数值(addrptraddr
44、ptr指向)转换成指向)转换成ASCIIASCII字符串字符串(strptrstrptr指向)。指向)。lenlen代表转换目标的大小避免产生溢出缓冲区的错误。代表转换目标的大小避免产生溢出缓冲区的错误。203.4 带外数据带外数据带外数据也称为带外数据也称为带外数据也称为带外数据也称为TCPTCP紧急数据。在流套接字的抽象中紧急数据。在流套接字的抽象中紧急数据。在流套接字的抽象中紧急数据。在流套接字的抽象中包括了带外数据这一概念。带外数据是每一对相连包括了带外数据这一概念。带外数据是每一对相连包括了带外数据这一概念。带外数据是每一对相连包括了带外数据这一概念。带外数据是每一对相连流套接字间逻
45、辑上独立的传输通道。带外数据是独流套接字间逻辑上独立的传输通道。带外数据是独流套接字间逻辑上独立的传输通道。带外数据是独流套接字间逻辑上独立的传输通道。带外数据是独立于普通数据传送给用户的。这要求带外数据设备立于普通数据传送给用户的。这要求带外数据设备立于普通数据传送给用户的。这要求带外数据设备立于普通数据传送给用户的。这要求带外数据设备必须支持每一时刻至少一个带外数据消息被可靠的必须支持每一时刻至少一个带外数据消息被可靠的必须支持每一时刻至少一个带外数据消息被可靠的必须支持每一时刻至少一个带外数据消息被可靠的传送。带外数据消息至少包含一个字节。在任何时传送。带外数据消息至少包含一个字节。在任
46、何时传送。带外数据消息至少包含一个字节。在任何时传送。带外数据消息至少包含一个字节。在任何时刻仅有一个带外数据信息等候发送。刻仅有一个带外数据信息等候发送。刻仅有一个带外数据信息等候发送。刻仅有一个带外数据信息等候发送。对于仅支持带内数据的通信协议来说(例如紧急数对于仅支持带内数据的通信协议来说(例如紧急数对于仅支持带内数据的通信协议来说(例如紧急数对于仅支持带内数据的通信协议来说(例如紧急数据是与普通数据在同一序列中发送的),系统通常据是与普通数据在同一序列中发送的),系统通常据是与普通数据在同一序列中发送的),系统通常据是与普通数据在同一序列中发送的),系统通常把紧急数据从普通数据中分离出
47、来单独存放。这就把紧急数据从普通数据中分离出来单独存放。这就把紧急数据从普通数据中分离出来单独存放。这就把紧急数据从普通数据中分离出来单独存放。这就允许用户可以在顺序接收紧急数据和非紧急数据之允许用户可以在顺序接收紧急数据和非紧急数据之允许用户可以在顺序接收紧急数据和非紧急数据之允许用户可以在顺序接收紧急数据和非紧急数据之间作出选择。间作出选择。间作出选择。间作出选择。213.5 连接类型连接类型进程经网络进行通信时,有两种方法可以选择:进程经网络进行通信时,有两种方法可以选择:进程经网络进行通信时,有两种方法可以选择:进程经网络进行通信时,有两种方法可以选择: 面向连接的方式:即虚电路方式。
48、这种方式是在两个连接面向连接的方式:即虚电路方式。这种方式是在两个连接面向连接的方式:即虚电路方式。这种方式是在两个连接面向连接的方式:即虚电路方式。这种方式是在两个连接端点之间建立一条虚电路,两端点之间的链路可以看作是端点之间建立一条虚电路,两端点之间的链路可以看作是端点之间建立一条虚电路,两端点之间的链路可以看作是端点之间建立一条虚电路,两端点之间的链路可以看作是直接的点到点的连接。两端点间只有在建立连接后才能传直接的点到点的连接。两端点间只有在建立连接后才能传直接的点到点的连接。两端点间只有在建立连接后才能传直接的点到点的连接。两端点间只有在建立连接后才能传输数据。一旦连接建立,双方均可
49、向对方发送非格式化的、输数据。一旦连接建立,双方均可向对方发送非格式化的、输数据。一旦连接建立,双方均可向对方发送非格式化的、输数据。一旦连接建立,双方均可向对方发送非格式化的、可靠的字符流。例如远程登录就是采用这种方式。可靠的字符流。例如远程登录就是采用这种方式。可靠的字符流。例如远程登录就是采用这种方式。可靠的字符流。例如远程登录就是采用这种方式。 无连接方式:即数据报方式。在传输报文前,不用建立连无连接方式:即数据报方式。在传输报文前,不用建立连无连接方式:即数据报方式。在传输报文前,不用建立连无连接方式:即数据报方式。在传输报文前,不用建立连接。无连接协议的每个报文包含一个完整的传送地
50、址。数接。无连接协议的每个报文包含一个完整的传送地址。数接。无连接协议的每个报文包含一个完整的传送地址。数接。无连接协议的每个报文包含一个完整的传送地址。数据按数据包形式传输。因此,某一进程可发送信息给某一据按数据包形式传输。因此,某一进程可发送信息给某一据按数据包形式传输。因此,某一进程可发送信息给某一据按数据包形式传输。因此,某一进程可发送信息给某一网络地址,然后再发信息给另一网络地址。网络地址,然后再发信息给另一网络地址。网络地址,然后再发信息给另一网络地址。网络地址,然后再发信息给另一网络地址。对应于进程的两种通信方式,套接字编程也有两种对应于进程的两种通信方式,套接字编程也有两种对应
51、于进程的两种通信方式,套接字编程也有两种对应于进程的两种通信方式,套接字编程也有两种模式。模式。模式。模式。 面向连接的模式面向连接的模式面向连接的模式面向连接的模式 面向无连接的编程模式面向无连接的编程模式面向无连接的编程模式面向无连接的编程模式223.6 TCP套接字套接字TCPTCP套接字实现过程套接字实现过程套接字实现过程套接字实现过程 服务器端步骤服务器端步骤服务器端步骤服务器端步骤 创建套接字创建套接字创建套接字创建套接字 绑定套接字绑定套接字绑定套接字绑定套接字 设置套接字为监听模式,进入被动接受连接请求状态设置套接字为监听模式,进入被动接受连接请求状态设置套接字为监听模式,进入
52、被动接受连接请求状态设置套接字为监听模式,进入被动接受连接请求状态 接受请求,建立连接接受请求,建立连接接受请求,建立连接接受请求,建立连接 读读读读/ /写数据写数据写数据写数据 终止连接终止连接终止连接终止连接 客户端步骤客户端步骤客户端步骤客户端步骤 创建套接字创建套接字创建套接字创建套接字 与远程服务程序连接与远程服务程序连接与远程服务程序连接与远程服务程序连接 读读读读/ /写数据写数据写数据写数据 终止连接终止连接终止连接终止连接2324#include #include #include #include #include #include main()main() int so
53、ckfd,connect_sock; int sockfd,connect_sock; /* /* 创创建建TCPTCP套接字套接字 * */ / if (sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) if (sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) perror( perror(“ “creating socket failed.creating socket failed.” ”); ); exit(1); exit(1); /* /* 绑绑定套接字定套接字 * */ / /* /* 监监听听 * */ / loo
54、p loop /* /* 接受接受请请求求连连接接 * */ / if (connect_sock=accept(sockfd,NULL,NULL)=-1) if (connect_sock=accept(sockfd,NULL,NULL)=-1) perror( perror(“ “Acception failed.Acception failed.” ”); ); exit(1); exit(1); /* /* 创创建子建子进进程或程或线线程以服程以服务务客客户户端端 * */ / TCP服务器模板服务器模板25TCP客户端模板客户端模板#include #include #include
55、 #include #include #include main()main() int sockfd; int sockfd; /* /* 创创建建TCPTCP套接字套接字 * */ / if (sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) if (sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) perror( perror(“ “creating socket failed.creating socket failed.” ”); ); exit(1); exit(1); /* /* 连连接服接服务务器和接收器和接收来来
56、自服自服务务器的器的数数据据 * */ / 263.6.2 实现实现TCP套接字套接字 对于基于对于基于对于基于对于基于TCPTCP的通信,无论是服务器还是客户,都必的通信,无论是服务器还是客户,都必的通信,无论是服务器还是客户,都必的通信,无论是服务器还是客户,都必须首先产生其须首先产生其须首先产生其须首先产生其TCPTCP通信传输端点,即通信传输端点,即通信传输端点,即通信传输端点,即TCPTCP套接字。套接字。套接字。套接字。应用程序通过调用应用程序通过调用应用程序通过调用应用程序通过调用socket()socket()产生套接字。该函数调用产生套接字。该函数调用产生套接字。该函数调用产
57、生套接字。该函数调用必须给出所使用的地址簇、套接字类型和协议标志。必须给出所使用的地址簇、套接字类型和协议标志。必须给出所使用的地址簇、套接字类型和协议标志。必须给出所使用的地址簇、套接字类型和协议标志。该函数返回一个套接字描述符。该函数返回一个套接字描述符。该函数返回一个套接字描述符。该函数返回一个套接字描述符。由于系统中套接字也是一种文件,所以套接字描述由于系统中套接字也是一种文件,所以套接字描述由于系统中套接字也是一种文件,所以套接字描述由于系统中套接字也是一种文件,所以套接字描述符是一种文件描述符。之后的任何符是一种文件描述符。之后的任何符是一种文件描述符。之后的任何符是一种文件描述符
58、。之后的任何I/OI/O操作都是作用操作都是作用操作都是作用操作都是作用于该套接字描述符。其数据结构包括一个网络连接于该套接字描述符。其数据结构包括一个网络连接于该套接字描述符。其数据结构包括一个网络连接于该套接字描述符。其数据结构包括一个网络连接的的的的5 5种信息:种信息:种信息:种信息:通信协议通信协议通信协议通信协议、本地协议地址本地协议地址本地协议地址本地协议地址、本机主机端本机主机端本机主机端本机主机端口口口口、远程主机地址远程主机地址远程主机地址远程主机地址和和和和远程协议端口远程协议端口远程协议端口远程协议端口。27socketsocket函数函数函数函数:为了执行网络输入输出
59、,一个进程必:为了执行网络输入输出,一个进程必:为了执行网络输入输出,一个进程必:为了执行网络输入输出,一个进程必须做的第一件事就是调用须做的第一件事就是调用须做的第一件事就是调用须做的第一件事就是调用socketsocket函数获得一个文件函数获得一个文件函数获得一个文件函数获得一个文件描述符。描述符。描述符。描述符。 #include int socket(int family,int type,int protocol); 返回:非负描述字成功-1失败第一个参数指明了协议簇,目前支持5种协议簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议);第二个参数指明套接
60、口类型,有三种类型可选:SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和SOCK_RAW(原始套接口);如果套接口类型不是原始套接口,那么第三个参数就为0。 28connectconnect函数函数函数函数:当用:当用:当用:当用socketsocket建立了套接口后,可以调建立了套接口后,可以调建立了套接口后,可以调建立了套接口后,可以调用用用用connectconnect为这个套接字指明远程端的地址;如果是为这个套接字指明远程端的地址;如果是为这个套接字指明远程端的地址;如果是为这个套接字指明远程端的地址;如果是字节流套接口,字节流套接口,字节流套接口,字节流
61、套接口,connectconnect就使用三次握手建立一个连就使用三次握手建立一个连就使用三次握手建立一个连就使用三次握手建立一个连接;如果是数据报套接口,接;如果是数据报套接口,接;如果是数据报套接口,接;如果是数据报套接口,connectconnect仅指明远程端地仅指明远程端地仅指明远程端地仅指明远程端地址,而不向它发送任何数据。址,而不向它发送任何数据。址,而不向它发送任何数据。址,而不向它发送任何数据。 #include int connect(int sockfd,const struct sockaddr * servaddr,socklen_t addrlen); 返回:0成功
62、-1失败 第一个参数是socket函数返回的套接口描述字;第二和第三个参数分别是一个指向套接口地址结构的指针和该结构的大小。 29bindbind函数函数函数函数:为套接口分配一个本地:为套接口分配一个本地:为套接口分配一个本地:为套接口分配一个本地IPIP和协议端口,和协议端口,和协议端口,和协议端口,对于网际协议,协议地址是对于网际协议,协议地址是对于网际协议,协议地址是对于网际协议,协议地址是3232位位位位IPv4IPv4地址或地址或地址或地址或128128位位位位IPv6IPv6地址与地址与地址与地址与1616位的位的位的位的TCPTCP或或或或UDPUDP端口号的组合;如指端口号的
63、组合;如指端口号的组合;如指端口号的组合;如指定端口为定端口为定端口为定端口为0 0,调用,调用,调用,调用bindbind时内核将选择一个临时端口,时内核将选择一个临时端口,时内核将选择一个临时端口,时内核将选择一个临时端口,如果指定一个通配如果指定一个通配如果指定一个通配如果指定一个通配IPIP地址,则要等到建立连接后内地址,则要等到建立连接后内地址,则要等到建立连接后内地址,则要等到建立连接后内核才选择一个本地核才选择一个本地核才选择一个本地核才选择一个本地IPIP地址。地址。地址。地址。 #include int bind(int sockfd,const struct sockadd
64、r * myaddr,socklen_t addrlen); 返回:0成功-1失败第一个参数是socket函数返回的套接口描述字;第二和第第三个参数分别是一个指向特定于协议的地址结构的指针和该地址结构的长度。 30listenlisten函数函数函数函数:listenlisten函数仅被函数仅被函数仅被函数仅被TCPTCP服务器调用,它的作用是将服务器调用,它的作用是将服务器调用,它的作用是将服务器调用,它的作用是将用用用用socksock创建的主动套接口转换成被动套接口,并等待来自客创建的主动套接口转换成被动套接口,并等待来自客创建的主动套接口转换成被动套接口,并等待来自客创建的主动套接口转
65、换成被动套接口,并等待来自客户端的连接请求。户端的连接请求。户端的连接请求。户端的连接请求。 #include int listen(int sockfd,int backlog); 返回:0成功-1失败第一个参数是socket函数返回的套接口描述字;第二个参数规定了内核为此套接口排队的最大连接个数。由于listen函数第二个参数的原因,内核要维护两个队列:以完成连接队列和未完成连接队列。未完成队列中存放的是TCP连接的三路握手为完成的连接,accept函数是从以连接队列中取连接返回给进程;当以连接队列为空时,进程将进入睡眠状态。 31acceptaccept函数函数函数函数:acceptac
66、cept函数由函数由函数由函数由TCPTCP服务器调用,从已完成连接服务器调用,从已完成连接服务器调用,从已完成连接服务器调用,从已完成连接队列头返回一个已完成连接,如果完成连接队列为空,则进队列头返回一个已完成连接,如果完成连接队列为空,则进队列头返回一个已完成连接,如果完成连接队列为空,则进队列头返回一个已完成连接,如果完成连接队列为空,则进程进入睡眠状态。程进入睡眠状态。程进入睡眠状态。程进入睡眠状态。 #include int accept(int sockfd,struct sockaddr *cliaddr,socklen_t * addrlen); 返回:非负描述字成功-1失败
67、第一个参数是socket函数返回的套接口描述字;第二个和第三个参数分别是一个指向连接方的套接口地址结构和该地址结构的长度;该函数返回的是一个全新的套接口描述字;如果对客户段的信息不感兴趣,可以将第二和第三个参数置为空。 323.6.3 数据传输数据传输int Send(int sockfd, const void * data, int data_len, unsigned int flags)功能:功能:在在TCPTCP连接上发送数据连接上发送数据, ,返回成功传送数据的长度,出错时返返回成功传送数据的长度,出错时返回回1 1。sendsend会将外发数据复制到会将外发数据复制到OSOS内核
68、中,也可以使用内核中,也可以使用sendsend发送面发送面向连接的向连接的UDPUDP报文。报文。参数说明:参数说明:uusockfdsockfd: :套接字描述符套接字描述符uudata:data:指向要发送数据的指针指向要发送数据的指针uudata_lendata_len: :数据长度数据长度uuflags:flags:一直为一直为0 0举例举例(p50)(p50):send(s,req,strlen(req),0);send(s,req,strlen(req),0);33int Sendto(int sockfd, const void * data, int int Sendto(i
69、nt sockfd, const void * data, int data_len, unsigned int flags, struct sockaddr data_len, unsigned int flags, struct sockaddr *remaddr,int remaddr_len*remaddr,int remaddr_len)功能:基于功能:基于UDPUDP发送数据报,返回实际发送的数据长度,出错发送数据报,返回实际发送的数据长度,出错时返回时返回1 1参数说明参数说明:sockfdsockfd: :套接字描述符套接字描述符data:data:指向要发送数据的指针指向要发
70、送数据的指针data_lendata_len: :数据长度数据长度flags:flags:一直为一直为0 0remaddrremaddr: :远端地址:远端地址:IPIP地址和端口号地址和端口号remaddr_lenremaddr_len : :地址长度地址长度举例:举例:sendto(sockfd,buf,sizeof(buf),0,(struct sendto(sockfd,buf,sizeof(buf),0,(struct sockaddrsockaddr *)&address, *)&address, sizeof(addresssizeof(address);); 34int rec
71、v(int sockfd, void *buf, int buf_len,unsigned int flags); 功能:功能:从从TCPTCP接收数据接收数据, ,返回实际接收的数据长度,出错时返回返回实际接收的数据长度,出错时返回1 1。服务器使用其接收客户请求,客户使用它接受服务器的应答。如果没有数据,服务器使用其接收客户请求,客户使用它接受服务器的应答。如果没有数据,将阻塞将阻塞,如果收到的数据大于缓存的大小,多余的数据将丢弃。也可以使用如果收到的数据大于缓存的大小,多余的数据将丢弃。也可以使用recvrecv接收面向连接的接收面向连接的UDPUDP的报文的报文参数说明:参数说明:uu
72、SockfdSockfd: :套接字描述符套接字描述符uuBufBuf: :指向内存块的指针指向内存块的指针uuBuf_lenBuf_len: :内存块大小,以字节为单位内存块大小,以字节为单位uuflags:flags:一般为一般为0 0 举例:举例:recv(sockfd,buf,8192,0)recv(sockfd,buf,8192,0)35int recvfrom(int sockfd, void *buf, int int recvfrom(int sockfd, void *buf, int buf_len,unsigned int flags,struct sockaddr bu
73、f_len,unsigned int flags,struct sockaddr *from,int fromlen);*from,int fromlen);功能:从功能:从UDPUDP接收数据,返回实际接收的字节数,失败时返回接收数据,返回实际接收的字节数,失败时返回1 1参数说明:参数说明:uuSockfdSockfd: :套接字描述符套接字描述符uubufbuf: :指向内存块的指针指向内存块的指针uubuf_lenbuf_len: :内存块大小,以字节为单位内存块大小,以字节为单位uuflags:flags:一般为一般为0 0uufrom:from:远端的地址,远端的地址,IPIP地址
74、和端口号地址和端口号uufromlenfromlen: :远端地址长度远端地址长度举例:举例:recvfrom(sockfd,buf,8192,0, ,(recvfrom(sockfd,buf,8192,0, ,(structstruct sockaddrsockaddr *)&address, *)&address, sizeof(addresssizeof(address);); 363.6.4 服务进程的创建服务进程的创建服务器端的进程需要对客户来的请求随时进行服务器端的进程需要对客户来的请求随时进行响应,因此需要服务器创建新进程的一些函数。响应,因此需要服务器创建新进程的一些函数。fo
75、rk()函数函数 #include #include int fork(void); int fork(void); fork() fork()函数最特殊的地方就是调用一次返回两次:父进函数最特殊的地方就是调用一次返回两次:父进函数最特殊的地方就是调用一次返回两次:父进函数最特殊的地方就是调用一次返回两次:父进程的返回值是所创建的子进程的程的返回值是所创建的子进程的程的返回值是所创建的子进程的程的返回值是所创建的子进程的IDID值;子进程的返回值值;子进程的返回值值;子进程的返回值值;子进程的返回值是是是是0 0。所以可以从返回值来判断这两次返回是在哪个进程。所以可以从返回值来判断这两次返回是
76、在哪个进程。所以可以从返回值来判断这两次返回是在哪个进程。所以可以从返回值来判断这两次返回是在哪个进程完成的。若返回完成的。若返回完成的。若返回完成的。若返回-1-1,则调用出错。,则调用出错。,则调用出错。,则调用出错。37 fork()函数一般有两个用途:函数一般有两个用途:父进程可以通过调用父进程可以通过调用父进程可以通过调用父进程可以通过调用fork()fork()函数来建立自己的拷贝函数来建立自己的拷贝函数来建立自己的拷贝函数来建立自己的拷贝子进程,从而在一个子进程执行任务时另外的子子进程,从而在一个子进程执行任务时另外的子子进程,从而在一个子进程执行任务时另外的子子进程,从而在一个
77、子进程执行任务时另外的子进程同时执行其他的操作。进程同时执行其他的操作。进程同时执行其他的操作。进程同时执行其他的操作。如果进程需要执行其他程序,则应该首先用如果进程需要执行其他程序,则应该首先用如果进程需要执行其他程序,则应该首先用如果进程需要执行其他程序,则应该首先用fork()fork()生成一个拷贝,然后这个拷贝子进程调用生成一个拷贝,然后这个拷贝子进程调用生成一个拷贝,然后这个拷贝子进程调用生成一个拷贝,然后这个拷贝子进程调用exec()exec()函数来执行应用程序。函数来执行应用程序。函数来执行应用程序。函数来执行应用程序。父进程调用父进程调用父进程调用父进程调用fork()fo
78、rk()前打开的所有套接字描述符都与子前打开的所有套接字描述符都与子前打开的所有套接字描述符都与子前打开的所有套接字描述符都与子进程共享。一般服务器调用进程共享。一般服务器调用进程共享。一般服务器调用进程共享。一般服务器调用accept()accept()后调用后调用后调用后调用fork()fork(),然后子进程继承了然后子进程继承了然后子进程继承了然后子进程继承了accept()accept()的已连接套接字描述符并的已连接套接字描述符并的已连接套接字描述符并的已连接套接字描述符并与之进行通信,而父进程则可以关闭这个套接字。与之进行通信,而父进程则可以关闭这个套接字。与之进行通信,而父进程
79、则可以关闭这个套接字。与之进行通信,而父进程则可以关闭这个套接字。38 exec() exec()函数函数函数函数 用来执行以文件形式存储在磁盘上的可执行程序。用来执行以文件形式存储在磁盘上的可执行程序。用来执行以文件形式存储在磁盘上的可执行程序。用来执行以文件形式存储在磁盘上的可执行程序。 #include #include int execl(const char * int execl(const char *pathnamepathname,const char *,const char *arg(),arg(), .); .); int execv(const char * int
80、execv(const char *pathnamepathname, char *const , char *const argv,argv, .); .); int execle(const char * int execle(const char *pathnamepathname,const char *,const char *arg(),arg(), .); .); int execve(const char * int execve(const char *pathnamepathname, char *const , char *const argv,argv, char *c
81、onst char *const envpenvp ); ); int execlp(const char * int execlp(const char *filenamefilename,const char *,const char *arg(),arg(), .); .); int execvp(const char * int execvp(const char *filenamefilename,char *const ,char *const argv argv );); pathnamepathname代表一个完整可执行程序的路径名,函数代表一个完整可执行程序的路径名,函数代表
82、一个完整可执行程序的路径名,函数代表一个完整可执行程序的路径名,函数execlpexeclp和和和和execvpexecvp相应的参数是相应的参数是相应的参数是相应的参数是filenamefilename,是根据,是根据,是根据,是根据 PATH PATH 环境变量转换成完整路径名;环境变量转换成完整路径名;环境变量转换成完整路径名;环境变量转换成完整路径名;argarg() ()和和和和argarg是命令行参数,空指针用来表示可变数量参数的终止。是命令行参数,空指针用来表示可变数量参数的终止。是命令行参数,空指针用来表示可变数量参数的终止。是命令行参数,空指针用来表示可变数量参数的终止。 函
83、数若成功则无返回,若出错则返回函数若成功则无返回,若出错则返回函数若成功则无返回,若出错则返回函数若成功则无返回,若出错则返回-1-1。393.6.5 终止连接终止连接close()close()函数函数函数函数 用来关闭一个套接字描述符。当完成了套接字的建立、绑用来关闭一个套接字描述符。当完成了套接字的建立、绑用来关闭一个套接字描述符。当完成了套接字的建立、绑用来关闭一个套接字描述符。当完成了套接字的建立、绑定、连接和通信读写之后,都需要最后关闭建立的套接字。定、连接和通信读写之后,都需要最后关闭建立的套接字。定、连接和通信读写之后,都需要最后关闭建立的套接字。定、连接和通信读写之后,都需要
84、最后关闭建立的套接字。 #include #include int close(int sockfd); int close(int sockfd); SockfdSockfd是需要关闭的套接字描述符。若执行成功则返回是需要关闭的套接字描述符。若执行成功则返回是需要关闭的套接字描述符。若执行成功则返回是需要关闭的套接字描述符。若执行成功则返回0 0,否则返回,否则返回,否则返回,否则返回-1-1。 清除套接字描述符的具体操作:将这个套接字描述符标记清除套接字描述符的具体操作:将这个套接字描述符标记清除套接字描述符的具体操作:将这个套接字描述符标记清除套接字描述符的具体操作:将这个套接字描述符标
85、记为为为为CLOSEDCLOSED状态,然后立即返回进程。状态,然后立即返回进程。状态,然后立即返回进程。状态,然后立即返回进程。TCPTCP协议将继续使协议将继续使协议将继续使协议将继续使用这个套接字,将尚未发送的数据传递到对方,然后发送用这个套接字,将尚未发送的数据传递到对方,然后发送用这个套接字,将尚未发送的数据传递到对方,然后发送用这个套接字,将尚未发送的数据传递到对方,然后发送FINFIN数据段,关闭和释放这个套接字。这是套接字才被完数据段,关闭和释放这个套接字。这是套接字才被完数据段,关闭和释放这个套接字。这是套接字才被完数据段,关闭和释放这个套接字。这是套接字才被完全删除。全删除
86、。全删除。全删除。 40 shutdown()函数函数可以部分关闭可以部分关闭可以部分关闭可以部分关闭socketsocket连接,单方面的中断连接,连接,单方面的中断连接,连接,单方面的中断连接,连接,单方面的中断连接,即禁止某个方向的信息传递。即禁止某个方向的信息传递。即禁止某个方向的信息传递。即禁止某个方向的信息传递。 #include #include int shutdown(int int shutdown(int sockfdsockfd,int ,int howhow);); sockfd sockfd代表需要关闭的套接字描述符;代表需要关闭的套接字描述符;代表需要关闭的套接字
87、描述符;代表需要关闭的套接字描述符;howhow的值:的值:的值:的值: 0 0:禁止接收信息:禁止接收信息:禁止接收信息:禁止接收信息 1: 1: 禁止发送信息禁止发送信息禁止发送信息禁止发送信息 2 2:接收和发送都被禁止,与:接收和发送都被禁止,与:接收和发送都被禁止,与:接收和发送都被禁止,与close()close()函数效果相同。函数效果相同。函数效果相同。函数效果相同。41 close()和和shutdown()的区别:的区别: close()close()函数调用时将访问计数减函数调用时将访问计数减函数调用时将访问计数减函数调用时将访问计数减1 1,只有当访问,只有当访问,只有
88、当访问,只有当访问计数减少到计数减少到计数减少到计数减少到0 0以后,才关闭套接字;而以后,才关闭套接字;而以后,才关闭套接字;而以后,才关闭套接字;而shutdown()shutdown()函数可直接发送函数可直接发送函数可直接发送函数可直接发送FINFIN数据段以终止网络连接,而数据段以终止网络连接,而数据段以终止网络连接,而数据段以终止网络连接,而不管访问计数的多少。不管访问计数的多少。不管访问计数的多少。不管访问计数的多少。 shutdown() shutdown()实际上只关闭了实际上只关闭了实际上只关闭了实际上只关闭了TCPTCP连接的一半。因连接的一半。因连接的一半。因连接的一半
89、。因为为为为TCPTCP连接是双向的,即包括读和写两个方向。连接是双向的,即包括读和写两个方向。连接是双向的,即包括读和写两个方向。连接是双向的,即包括读和写两个方向。ShutdownShutdown() ()函数可以给服务器发送一个函数可以给服务器发送一个函数可以给服务器发送一个函数可以给服务器发送一个FINFIN,告诉它已经完,告诉它已经完,告诉它已经完,告诉它已经完成了数据发送,但仍为读而开放套接字描述符。成了数据发送,但仍为读而开放套接字描述符。成了数据发送,但仍为读而开放套接字描述符。成了数据发送,但仍为读而开放套接字描述符。CloseClose() ()函数则是同时关闭了读写两个方
90、向。函数则是同时关闭了读写两个方向。函数则是同时关闭了读写两个方向。函数则是同时关闭了读写两个方向。423.6.6 连接地址信息获取连接地址信息获取gethostname()43套接字API中的主要系统调用readread和和writewrite 在在UNIXUNIX和和LinuxLinux中,可以代替中,可以代替recvrecv和和send,send,因为都调因为都调用内核的用内核的sosendsosend实现。实现。小结:小结:socket*connect*send(write)*recv(read)*close*bindlistenacceptrecvmsgsendmsgrecvfromsendtoshutdowngetpeernamegetsockoptsetsockopt44