1、Unix网络编程API1.字节序函数#include uint16_t htons(uint16_t host16bitvalue);uint32_t htonl(uint32_t host32bitvalue);返回:网络字节序值uint16_t ntohs(uint16_t net16bitvalue);uint32_t ntohl(uint32_t net32bitvalue);返回:主机字节序值一个测试本机字节序的程序,可参见见unpv12e:intro/byteorder.c。2.字节操作函数#include void bzero(void *dest, size_t nbytes)
2、;void bcopy(const void *src, void *dest, size_t nbytes);int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);返回:0相等,非0不相等#include void *memset(void *dest, int c, size_t len);void *memcpy(void *dest, void *src, size_t nbytes);int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);返回:0相同
3、,0或0不相同;进行比较操作时,假定两个不相等的字节均为无符号字符(unsigned char)。3.地址转换函数#include int inet_aton(const char *strptr, struct in_addr *addrptr);返回:1串有效,0串有错。in_addr_t inet_addr(const char *strptr);返回:若成功,返回32为二进制的网络字节序地址;若有错,则返回INADDR_NONE。char *inet_ntoa(struct in_addr inaddr);返回:指向点分十进制数串的指针。int inet_pton(int family
4、, const char *strptr, void *addrptr);返回:1成功;0输入不是有效的表达格式,-1出错。const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);返回:指向结果的指针成功,NULL失败。说明: inet_aton函数的指针若为空,则函数仍然执行输入串的有效性检查,但不存储任何结果。 inet_addr的缺陷:出错返回值INADDR_NONE等于255.255.255.255(IPv4的有限广播地址),所以该函数不能处理此地址。尽量使用inet_aton,不
5、使用inet_addr。 inet_ntoa函数的执行结果放在静态内存中,是不可重入的。 参数family可以是AF_INET,也可以是AF_INET6,若参数family不被支持,则出错,errno置为EAFNOSUPPORT。 指针addrptr是结构指针。 len指定目标的大小,避免缓冲区溢出。如果len太小,则返回一个空指针,errno置为ENOSPC。为有助于规定该大小,有如下定义:#include #define INET_ADDRSTRLEN 16 /*fro IPv4 dotted-decimal */#define INET6_ADDRSTRLEN 46 /*for IPv6
6、 hex string */ inet_ntop函数的参数strptr不能为空指针,成功时,此指针即是函数的返回值。实现IPv4版本的inet_pton和inet_ntop的程序,参见:unpv12e:libfree/inet_pton_ipv4.c和libfree/inet_ntop_ipv4.c。4.readn、writen和readline函数原型如下:ssize_t readn(int filedes, void *buff, size_t nbytes);ssize-t writen(int filedes, void *buff, size_t nbytes);ssize_t re
7、adline(int filedes, void *buff, size_t maxlen);返回:读写字节数,-1出错。实现程序见:unpv12e:lib/readn.c、lib/writen.c、lib/readline1.c和lib/readline.c。5.测试描述符类型#include int isfdtype( int fd, int fdtype);返回:1是指定类型,0不是指定类型,-1出错。要测试是否为套接口描述子,fdtype应设为S_IFSOCK。该函数的一个实现程序,参见unpv12e:lib/isfdtype.c6.socket函数#include int socke
8、t(int family, int type, int protocol);返回:非负描述字成功,-1出错。family指定协议族,有如下取值: AF_INETIPv4协议 AF_INET6IPv6协议 AF_LOCALUnix域协议 AF_ROUTE路由套接口 AF_KEY密钥套接口type指定套接口类型: SOCK_STREAM字节流套接口 SOCK_DGRAM数据报套接口 SOCK_RAW原始套接口protocol一般设为0,除非用在原始套接口上。并非所有family和type的组合都是有效的。AF_LOCAL等于早期的AF_UNIX。7.connect函数#include int co
9、nnect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);返回:0成功,-1出错。sockfd是socket函数返回的套接口描述字,servaddr和addrlen是指向服务器的套接口地址结构指针和结构大小。在调用connect之前不必非得调用bind函数。如果是TCP,则connect激发TCP的三路握手过程,在阻塞情况下,只有在连接建立成功或出错时该函数才返回,出错情况: 没有收到SYN分节的响应,在规定时间内经过重发仍无效,则返回ETIMEDOUT; 如果对SYN分节的响应是RST,表示服务器在指定端口上没
10、有相应的服务,返回ECONNREFUSED; 如果发出 SYN在中间路由器上引发一个目的地不可达ICMP错误,在规定时间内经过重发仍无效,则返回EHOSTUNREACH或ENETUNREACH错误。注意:如果connect失败,则套接口将不能再使用,必须关闭,不能对此套接口再调用函数connect。8.bind函数#include int bind(int sockfd, const struct sockaddr *maddr, socklen_t addrlen);返回:0成功,-1出错。进程可以把一个特定的IP地址捆绑到他的套接口上,但此IP地址必须是主机的一个接口。对于IPv4,通配地
11、址是INADDR_ANY,其值一般为0;使用方法如下:struct sockaddr_in servaddr;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);对于IPv6,方法如下:struct sockaddr_in6 serv;serv.sin6_addr = in6addr_any; (系统分配变量in6addr_any并将其初始化为常值IN6ADDR_ANY_INIT。)如果让内核选择临时端口,注意的是bind并不返回所选的断口值,要得到一个端口,必须使用getsockname函数。bind失败的常见错误是EADDRINUSE(地址已使用)。9
12、.listen函数#include int listen(int sockfd, int backlog);返回:0成功,-1出错。listen把未连接的套接口转化为被动套接口,指示内核应接受指向此套接口的连接请求。第二个参数规定了内核为此套接口排队的最大连接数。参数backlog曾经规定为监听套接口上的未完成连接队列和已完成连接队列总和的最大值,但各个系统的定义方法都不尽相同;历史上常把backlog置为5,但对于繁忙的服务器是不够的;backlog的设置没有一个通用的方法,依情况而定,但不要设为0。10.accept函数#include int accept(int sockfd, str
13、uct sockaddr *cliaddr, socklen_t *addrlen);返回:非负描述字OK,-1出错。accept从已完成连接队列头返回下一个连接,若已完成连接队列为空,则进程睡眠(套接口为阻塞方式时)。参数cliaddr和addrlen返回连接对方的协议地址,其中addrlen是值-结果参数,调用前addrlen所指的整数值要置为cliaddr所指的套接口结构的长度,返回时由内核修改。accept成功执行后,返回一个连接套接口描述字。如果对客户的协议地址没有兴趣,可以把cliaddr和addrlen置为空指针。11.close函数#include int close(int
14、sockfd);返回:0OK,-1出错。TCP套接口的close缺省功能是将套接口做上“已关闭”标记,并立即返回到进程。这个套接口描述字不能再为进程使用,但TCP将试着发送已排队待发的任何数据,然后按正常的TCP连接终止序列进行操作。close把描述字的访问计数减1,当访问计数仍大于0时,close并不会引发TCP的四分组连接终止序列。若确实要发一个FIN,可以用函数shutdown。12.getsockname和getpeername#include int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addr
15、len);int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);返回:0OK,-1出错。getsockname函数返回与套接口关联的本地协议地址。getpeername函数返回与套接口关联的远程协议地址。addrlen是值-结果参数。使用场合: 在不调用bind的TCP客户,当connect成功返回后,getsockname返回分配给此连接的本地IP地址和本地端口号; 在以端口号为0调用bind后,使用getsockname返回内核分配的本地端口号; getsockname可用来获取某套接口的地址族
16、; 在捆绑了通配IP地址的TCP服务器上,当连接建立后,可以使用getsockname获得分配给此连接的本地IP地址; 当一个服务器调用exec启动后,他获得客户身份的唯一途径是调用getpeername函数。13.select函数#include #include int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);返回:准备好描述字的正数目,0超时,-1出错。结构timeval的定义:struct timeval long t
17、v_sec; /* seconds */long tv_usec; /* microseconds */;timeout取值的三种情况: 永远等下去:仅在有一个描述字准备好I/O时才返回,设置timeout为空指针; 等待固定时间:在有一个描述字准备好I/O时返回,但不超过由timeout参数所指定的秒数和微秒数; 根本不等待:检查描述字后立即返回,将timeout中的秒数和微秒数都设置为0。在等待过程中,若进程捕获了信号并从信号处理程序返回,等待一般被中断,为了可移植性,必须准备好select返回EINTR错误。timeout的值在返回时并不会被select修改(const标志)。reads
18、et、writeset、exceptset指定我们要让内核测试读、写和异常条件所需的描述字。当前支持的异常条件有两个:1. 套接口带外数据的到达;2. 控制状态信息的存在,可从一个已置为分组方式的伪终端主端读到。描述字集的使用:数据类型:fd_set;void FD_ZERO(fd_set *fdset);void FD_SET(int fd, fd_set *fdset);void FD_CLR(int fd, fd_set *fdset);void FD_ISSET(int fd, fd_set *fdset);参数maxfdp1指定被测试的描述字个数,它的值是要被测试的最大描述字加1。描
19、述字0,1,2,maxfdp1-1都被测试。readset、writeset、exceptset是值-结果参数,select修改三者所指的描述字集。所以,每次调用select时,我们都要将所有描述字集中关心的位置为1。套接口准备好读的条件: 套接口接收缓冲区中的数据字节数大于等于套接口接收缓冲区低潮限度的当前值。对这样的套接口的读操作将不阻塞并返回一个大于0的值(即准备好读入的数据量)。可以用套接口选项SO_RCVLOWAT来设置低潮限度,对于TCP和UDP,缺省值为1; 连接的读这一半关闭(接收了FIN的TCP连接)。对这样的套接口读操作将不阻塞并且返回0(即文件结束符); 套接口是一个监听
20、套接口且已完成的连接数为非0; 有一个套接口错误待处理。对这样的套接口读操作将不阻塞且返回一个错误,errno设置成明确的错误条件。这些待处理错误也可以通过指定套接口选项SO_ERROR调用getsockopt来取得并清除。套接口准备好写的条件: 套接口发送缓冲区中的可用字节数大于等于套接口发送缓冲区低潮限度的当前值,且或者(1)套接口已连接,或者(2)套接口不要求连接(如UDP套接口)。可以用套接口选项SO_SNDLOWAT来设置此低潮限度,对于TCP和UDP,缺省值为2048; 连接的写这一半关闭。对这样的套接口写将产生信号SIGPIPE; 有一个套接口错误待处理。对这样的套接口写操作将不
21、阻塞且返回一个错误,errno设置成明确的错误条件。这些待处理错误也可以通过指定套接口选项SO_ERROR调用getsockopt来取得并清除。如果一个套接口存在带外数据或者仍处于带外标记,那它有异常条件待处理。一个套接口出错时,它被select标记为既可读又可写。14.shutdown函数#include int shutdown(int sockfd, int howto);返回:0成功,-1失败。函数的行为依赖于参数howto的值: SHUT_RD:关闭连接的读这一半,不再接收套接口中的数据且留在套接口缓冲区中的数据都作废。进程不能再对套接口任何读函数。调用此函数后,由TCP套接口接收的
22、任何数据都被确认,但数据本身被扔掉。 SHUT_WR:关闭连接的写这一半,在TCP场合下,这称为半关闭。当前留在套接口发送缓冲区中的数据都被发送,后跟正常的TCP连接终止序列。此半关闭不管套接口描述字的访问计数是否大于0。进程不能再执行对套接口的任何写函数。SHUT_RDWR:连接的读这一半和写这一半都关闭。这等效于调用shutdown两次:第一次调用时用SHUT_RD,第二次调用时用SHUT_WR。15.pselect函数#include #include #include int pselect(int maxfdp1, fd_set *readset, fd_set *writeset,
23、 fd_set *exceptset, const struct timespec *timeout, const sigset_t *sigmask);返回:准备好描述字的个数,0超时,-1出错。pselect是Posix.1g发明的。相对select的变化:1. pselect使用结构timespec:struct timespec time_t tv_sec; /* seconds */long tv_nsec; /* nanoseconds */;新结构中的tv_nsec规定纳秒数。2. pselect增加了第六个参数:指向信号掩码的指针。允许程序禁止递交某些信号。16.poll函数#
24、include int poll(struct pollfd *fdarray, unsigned long nfds, int timeout);返回:准备好描述字的个数,0超时,-1出错。第一个参数是指向一个结构数组的第一个元素的指针,每个数组元素都是一个pollfd结构:struct pollfd int fd; /* descriptor to check */short events; /* events of interest on fd */short revents; /* events that occurred on fd */;要测试的条件由成员events规定,函数在相
25、应的revents成员中返回描述字的状态(一个描述字有两个变量:一个为调用值,一个为结果)。第二个参数指定数组中元素的个数。第三个参数timeout指定函数返回前等待多长时间,单位是毫秒。可能值如下: INFTIM,永远等待; 0,立即返回,不阻塞; 0,等待指定数目的毫秒数。标志的范围:常量能作为events的输入吗?能作为revents的结果吗?解释POLLINyesyes普通或优先级带数据可读POLLRDNORMyesyes普通数据可读POLLRDBANDyesyes优先级带数据可读POLLPRIyesyes高优先级数据可读POLLOUTyesyes普通或优先级带数据可写POLLWRNO
26、RMyesyes普通数据可写POLLWRBANDyesyes优先级带数据可写POLLERRyes发生错误POLLHUPyes发生挂起POLLNVALyes描述字不是一个打开的文件图可分为三部分:处理输入的四个常值;处理输出的三个常值;处理错误的三个常值。poll识别三个类别的数据:普通(normal)、优先级带(priority band)、高优先级(high priority)。术语来自流的概念。返回条件: 所有正规TCP数据和UDP数据都被认为是普通数据; TCP的带外数据被认为是优先级带数据; 当TCP连接的读这一半关闭时(如接收了一个FIN),这也认为是普通数据,且后续的读操作将返回0
27、; TCP连接存在错误既可以认为是普通数据,也可以认为是错误(POLLERR)。无论哪种情况,后续的读操作将返回-1,并将errno置为适当的值,这就处理了诸如接收到RST或超时等条件; 在监听套接口上新连接的可用性既可认为是普通数据,也可以认为是优先级带数据,大多数实现都将其作为普通数据考虑。 如果不关心某个特定的描述字,可将其pollfd结构的fd成员置为一个负值,这样就可以忽略成员events,且返回时将成员revents的值置为0。poll没有select存在的最大描述字数目问题。但可移植性select要好于poll。17.getsockopt和setsockopt#include i
28、nt getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);返回:0OK,-1出错。sockfd必须是一个打开的套接口描述字;level(级别)指定系统中解释选项的代码:普通套接口代码或特定于协议的代码);optval是一个指向变量的指针;此变量的大小由最后一个参数决定。对于某些套接口选项,什么时候进行设置或获取是有差别的。
29、下面的套接口选项是由TCP已连接套接口从监听套接口继承来的: SO_DEBUG; SO_DONTROUTE; SO_KEEPALIVE; SO_LINGER; SO_OOBINLINE; SO_RCVBUF; SO_SNDBUF。如果想在三路握手完成时确保这些套接口选项中的某一个是给已连接套接口设置的,我们必须先给监听套接口设置此选项。18.套接口选项列表levelOptnamegetset说明标志数据类型SOL_SOCKETSO_BROADCASTyy允许发送广播数据报yintSO_DEBUGyy使能调试跟踪yintSO_DONTROUTEyy旁路路由表查询yintSO_ERRORy获取待处
30、理错误并消除intSO_KEEPALIVEyy周期性测试连接是否存活yintSO_LINGERyy若有数据待发送则延迟关闭lingerSO_OOBINLINEyy让接收到的带外数据继续在线存放yintSO_RCVBUFyy接收缓冲区大小intSO_SNDBUFyy发送缓冲区大小intSO_RCVLOWATyy接收缓冲区低潮限度intSO_SNDLOWATyy发送缓冲区低潮限度intSO_RCVTIMEOyy接收超时timevalSO_SNDTIMEOyy发送超时timevalSO_REUSEADDRyy允许重用本地地址yintSO_REUSEPORTyy允许重用本地地址yintSO_TYPEy
31、取得套接口类型intSO_USELOOPBACKyy路由套接口取得所发送数据的拷贝yintIPPROTO_IPIP_HDRINCLyyIP头部包括数据yintIP_OPTIONSyyIP头部选项见后面说明IP_RECVDSTADDRyy返回目的IP地址yintIP_RECVIFyy返回接收到的接口索引yintIP_TOSyy服务类型和优先权intIP_TTLyy存活时间intIP_MULTICAST_IFyy指定外出接口in_addrIP_MULTICAST_TTLyy指定外出TTLu_charIP_MULTICAST_LOOPyy指定是否回馈u_charIP_ADD_MEMBERSHIPy加
32、入多播组ip_mreqIP_DROP_MEMBERSHIPy离开多播组ip_mreqIPPROTO_ICMPV6ICMP6_FILTERyy指定传递的ICMPv6消息类型icmp6_filterIPPROTO_IPV6IPV6_ADDRFORMyy改变套接口的地址结构intIPV6_CHECKSUMyy原始套接口的校验和字段偏移intIPV6_DSTOPTSyy接收目标选项yintIPV6_HOPLIMITyy接收单播跳限yintIPV6_HOPOPTSyy接收步跳选项yintIPV6_NEXTHOPyy指定下一跳地址ysockaddrIPV6_PKTINFOyy接收分组信息yintIPV6_
33、PKTOPTIONSyy指定分组选项见后面说明IPV6_RTHDRyy接收原路径yintIPV6_UNICAST_HOPSyy缺省单播跳限intIPV6_MULTICAST_IFyy指定外出接口in6_addrIPV6_MULTICAST_HOPSyy指定外出跳限u_intIPV6_MULTICAST_LOOPyy指定是否回馈yu_intIPV6_ADD_MEMBERSHIPy加入多播组ipv6_mreqIPV6_DROP_MEMBERSHIPy离开多播组ipv6_mreqIPPROTO_TCPTCP_KEEPALIVEyy控测对方是否存活前连接闲置秒数intTCP_MAXRTyyTCP最大重
34、传时间intTCP_MAXSEGyyTCP最大分节大小intTCP_NODELAYyy禁止Nagle算法yintTCP_STDURGyy紧急指针的解释yint详细说明:SO_BROADCAST使能或禁止进程发送广播消息的能力。只有数据报套接口支持广播,并且还必须在支持广播消息的网络上(如以太网、令牌环网等)。如果目的地址是广播地址但此选项未设,则返回EACCES错误。SO_DEBUG仅仅TCP支持。当打开此选项时,内核对TCP在此套接口所发送和接收的所有分组跟踪详细信息。这些信息保存在内核的环形缓冲区内,可由程序trpt进行检查。SO_DONTROUTE此选项规定发出的分组将旁路底层协议的正常
35、路由机制。该选项经常由路由守护进程(routed和gated)用来旁路路由表(路由表不正确的情况下),强制一个分组从某个特定接口发出。SO_ERROR当套接口上发生错误时,源自Berkeley的内核中的协议模块将此套接口的名为so_error的变量设为标准的UNIX Exxx值中的一个,它称为此套接口的待处理错误(pending error)。内核可立即以以下两种方式通知进程:1. 如果进程阻塞于次套接口的select调用,则无论是检查可读条件还是可写条件,select都返回并设置其中一个或所有两个条件。2. 如果进程使用信号驱动I/O模型,则给进程或进程组生成信号SIGIO。进程然后可以通过
36、获取SO_ERROR套接口选项来得到so_error的值。由getsockopt返回的整数值就是此套接口的待处理错误。so_error随后由内核复位为0。当进程调用read且没有数据返回时,如果so_error为非0值,则read返回-1且errno设为so_error的值,接着so_error的值被复位为0。如果此套接口上有数据在排队,则read返回那些数据而不是返回错误条件。如果进程调用write时so_error为非0值,则write返回-1且errno设为so_error的值,随后so_error也被复位。SO_KEEPALIVE打开此选项后,如果2小时内在此套接口上没有任何数据交换,
37、TCP就会自动给对方发一个保持存活探测分节,结果如下:1. 对方以期望的ACK响应,则一切正常,应用程序得不到通知;2. 对方以RST响应,套接口的待处理错误被置为ECONNRESET,套接口本身则被关闭;3. 对方对探测分节无任何响应,经过重试都没有任何响应,套接口的待处理错误被置为ETIMEOUT,套接口本身被关闭;若接收到一个ICMP错误作为某个探测分节的响应,则返回相应错误。此选项一般由服务器使用。服务器使用它是为了检测出半开连接并终止他们。SO_LINGER此选项指定函数close对面向连接的协议如何操作(如TCP)。缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统
38、将试着将这些数据发送给对方。SO_LINGER选项用来改变此缺省设置。使用如下结构:struct linger int l_onoff; /* 0 = off, nozero = on */int l_linger; /* linger time */;有下列三种情况:1. l_onoff为0,则该选项关闭,l_linger的值被忽略,等于缺省情况,close立即返回;2. l_onoff为非0,l_linger为0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;3. l_onof
39、f 为非0,l_linger为非0,当套接口关闭时内核将拖延一段时间(由l_linger决定)。如果套接口缓冲区中仍残留数据,进程将处于睡眠状态,直到(a)所有数据发送完且被对方确认,之后进行正常的终止序列(描述字访问计数为0)或(b)延迟时间到。此种情况下,应用程序检查close的返回值是非常重要的,如果在数据发送完并被确认前时间到,close将返回EWOULDBLOCK错误且套接口发送缓冲区中的任何数据都丢失。close的成功返回仅告诉我们发送的数据(和FIN)已由对方TCP确认,它并不能告诉我们对方应用进程是否已读了数据。如果套接口设为非阻塞的,它将不等待close完成。l_linger
40、的单位依赖于实现,4.4BSD假设其单位是时钟滴答(百分之一秒),但Posix.1g规定单位为秒。让客户知道服务器已经读其数据的一个方法时:调用shutdown(SHUT_WR)而不是调用close,并等待对方close连接的本地(服务器)端。SO_OOBINLINE此选项打开时,带外数据将被保留在正常的输入队列中(即在线存放)。当发生这种情况时,接收函数的MSG_OOB标志不能用来读带外数据。SO_RCVBUF和SO_SNDBUF每个套接口都有一个发送缓冲区和一个接收缓冲区,使用这两个套接口选项可以改变缺省缓冲区大小。当设置TCP套接口接收缓冲区的大小时,函数调用顺序是很重要的,因为TCP的
41、窗口规模选项是在建立连接时用SYN与对方互换得到的。对于客户,SO_RCVBUF选项必须在connect之前设置;对于服务器,SO_RCVBUF选项必须在listen前设置。TCP套接口缓冲区的大小至少是连接的MSS的三倍,而必须是连接的MSS的偶数倍。SO_RCVLOWAT和SO_SNDLOWAT每个套接口有一个接收低潮限度和一个发送低潮限度,他们由函数select使用。这两个选项可以修改他们。接收低潮限度是让select返回“可读”而在套接口接收缓冲区中必须有的数据量,对于一个TCP或UDP套接口,此值缺省为1。发送低潮限度是让select返回“可写”而在套接口发送缓冲区中必须有的可用空间
42、,对于TCP套接口,此值常为2048。SO_RCVTIMEO和SO_SNDTIMEO使用这两个选项可以给套接口设置一个接收和发送超时。通过设置参数的值为0秒和0微秒来禁止超时。缺省时两个超时都是禁止的。接收超时影响5个输入函数:read、readv、recv、recvfrom和recvmsg;发送超时影响5个输出函数:write、writev、send、sendto和sendmsg。SO_REUSEADDR和SO_REUSEPORTSO_REUSEADDR提供如下四个功能:1. SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。2. SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。3. SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。4. SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,
©2010-2024 宁波自信网络信息技术有限公司 版权所有
客服电话:4008-655-100 投诉/维权电话:4009-655-100