欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

linux C语言函数API--网络编程函数

程序员文章站 2024-01-21 21:04:58
...

五:网络编程函数

1.socket()创建网络插口函数


【原型】    int socket(int domain,int type,int protocol);
【头文件】 #include<sys/types.h>
            #include<sys/socket.h>
【功能】    创建网络插口
【参数】    domain : 设置网络通信的域,选择通信协议的族。
                    PF_UNIX,PF_LOCAL 本地通信
                    PF_INET     :IPv4 Internet 协议
                    PF_INET6    :IPv6 internet 协议
                    PF_IPX      : IPX-Novell 协议
                    PF_NETLINK  :内核用户界面设备
                    PF_X25      : ITU-T X.25/ISO-8208协议
                    PF_AX25     : Amateur radio AX.25 协议
                    PF_ATMPVC   : 原始ATMPVC 访问
                    PF_APPLETALK: Appletalk
                    PF_PACKET   : 底层包访问

            type : 用于设置套接字通信的类型
                    SOCK_STREAM : TCP连接,提供序列化的、可靠的、双向连接的字节流。支持带外数据传输
                    SOCK_DGRAM  : 支持UDP连接(无连接状态的消息)
                    SOCK_SEQPACKET : 序列化包,提供序列化的,可靠的,双向连接的字节流。支持带外数据传输。
                    SOCK_RAW    : RAW 类型,提供原始网络协议访问
                    SOCK_RDM    :提供可靠的数据报文,不过可能数据会有乱序
                    SOCK_PACKET : 这是一个专用类型,不能在通用程序中使用。
                    注意:并不是所有的协议簇都实现了这些协议类型。例如:AF_INET协议簇就没有实现
                            SOCK_SEQPACKET协议类型。
            protocol : 用于指定某个协议的特定类型,即type类型中的某个类型。通常设置为0
            
【返回值】 成功:返回文件描述符
            失败:返回错误码errno
            
                errno的参数如下:
                
                EACCES  :没有权限建立指定的domain的type的socket
                EAFNOSUPPORT :不支持所给的地址类型
                EINVAL : 不支持此协议或者协议不可用。
                EMFILE :已经达到系统允许打开的文件数量,打开文件过多。
                ENOBUFS/ENOMEM : 内存不足,socket 只有到资源足够或者有进程释放内存
                EPROTONOSUPPORT : 指定的协议type在domain中不存在

【注意点】
            1. 有些协议有多种特定的类型,就需要设置protocol这个参数来选择特定的类型。
            2. 类型为SOCK_STREAM的套接字表示一个双向的字节流,与管道类似。
            3. 流式的套接字在进行数据收发之前必须已经连接。连接使用connect()函数进行
            4.  流式的通信方式保证数据不会丢失或者重复接收,
                当数据在一段时间内仍然没有接收完毕,可以将这个连接认为已经死掉。
            5. SOCK_PACKET是一种专用的数据包,它直接从设备驱动接收数据。
            6.  socket()并不总是执行成功,失败原因可以通过errno获得。
        
        



2. bind()绑定一个地址端口

    【原型】    int bind(int sockfd,const struct sockaddr *my_addr,socklen_t addrlen);
    【头文件】 #include <sys/types.h>
                #include <sys/socket.h>
    【功能】    绑定一个地址端口
    【参数】    sockfd : socket创建的socket描述符
addrlen :是my_addr结构体的长度,可以设置成sizeof(struct sockaddr);
                my_addr :是一个指向sockaddr的指针. 在中有 sockaddr的定义
					struct sockaddr
{ 
    unisgned short as_family;
    char sa_data[14];
};
不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct
sockaddr_in) 来代替.在中有sockaddr_in的定义
struct sockaddr_in
{
    						  unsigned short sin_family;		//存放地址协议类型  AF_INET
    unsigned short int sin_port; //存放你要绑定的端口号
    struct in_addr sin_addr;	//存放你要绑定的ip地址
    unsigned char sin_zero[8];	//是用来填充结构体大小的
};
struct in_addr
 {
    in_addr_t s_addr;
 };

     注意:      sin_addr设置为INADDR_ANY表示可以和任何的主机通信,如果需要指定,则自定义IP地址
    
    【返回值】 成功 0 失败 -1 或者其错误码errno
                errno 数值如下:
                    EADDRINUSE :给定地址已经使用
                    EBADF      : sockfd 不合法
                    EINVAL     : sockfd 已经绑定到其他地址
                    ENOTSOCK   : sockfd 是一个文件描述符,不是 socket描述符
                    EACCES     : 地址被保护,用户的权限不足
                    EADDRNOTAVAIL : 接口不存在或者绑定地址不是本地
                    EFAULT :    my_addr指针超出用户空间
                    EINVAL  :  地址长度错误,或者socket不是AF_UNIX族
                    ELOOP   : 解析my_addr是符号链接过多
                    ENAMETOOLONG :my_addr过长
                    ENOENT  :文件不存在
                    ENOMEM :内核内存不足
                    ENOTDIR:不是目录
                    EROFS :socket 节点应该在只读文件系统上
                    
    【注意点】
            1. sockaddr中包含了地址、端口和IP地址的信息。
            2. 在进行地址绑定的时候,需要先将地址结构中的IP地址、端口、类型等
                结构struct sockaddr 中的域进行设置后才能进行绑定,这样绑定后才能将
                套接字文件描述符与地址等结合在一起。
                    
    

                     

3. listen()监听本地端口

【原型】    int listen(int sockfd,int backlog);
    【头文件】 #include <sys/socket.h>
    【功能】 监听本地的端口
    【参数】 sockfd: socket创建的描述符。
             backlog: 表示等待队列的长度
             
    【返回值】 成功 0 ,失败 -1
                其错误码errno如下:
                    EADDRINUSE :另一个socket已经在同一端口侦听。
                    EBADF :参数sockfd不是合法的描述符
                    ENOTSOCK :参数sockfd不是代表socket的文件描述符
                    EOPNOTSUPP :socket不支持listen操作
                    
                    
    【注意点】 1. 在接受一个连接之前,需要用listen()函数来侦听端口
                    listen()函数中参数backlog的参数表示在accept()函数处理之前
                    在等待队列中的客户端的长度,如果超过这个长度,客户端会返回
                    一个ECONNREFUSED错误
                    
                2. listen()函数仅对类型为SOCK_STREAM或者SOCK_SEQPACKET的协议有效
                
                    

4. accept()接受一个网络请求

    【原型】    int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
    【头文件】 #include <sys/types.h> 
                #include <sys/socket.h>
    【功能】    接受一个网络请求
    【参数】    sockfd: 套接字文件描述符
                addr : socket相关数据:IP地址,端口,协议族等信息。
                addrlen :表示第2个参数(addr)所指内容的长度。
    【返回值】 成功:返回新套接字文件描述符。   
                失败: -1 
                错误码errno如下:
                EAGAIN/EWOULDBLOCK :此socket使用了非阻塞模式,当前情况下没有可接受的连接。
                EBADF :描述符非法
                ECONNABORTED :连接取消
                EINTR : 信号在合法连接到来之前打断了accept的系统调用
                EINVAL :socket 没有侦听到连接或者地址长度不合法
                EMFILE :每个进程允许打开的文件描述符数量最大值已经到达
                ENFILE :达到系统允许打开文件的总数量
                ENOTSOCK : 文件描述符是一个文件,不是socket
                EOPNOTSUPP : 引用的socket 不是流类型SOCK_STREAM
                EFAULT :参数addr不可写
                ENOBUFS/ENOMEM :内存不足
                EPROTO :协议错误
                EPERM :防火墙不允许连接。
            
            
   



       

5. connect() 连接目标网络服务器

    【原型】    int connect(int sockfd,struct sockaddr * serv_addr,int addrlen);
    【头文件】 #include <sys/types.h>
                #include <sys/socket.h>
    【功能】    连接目标网络服务器
    【参数】    sockfd : 建立套接字时返回的套件字文件描述符,由系统调用socket()返回的
                serv_addr :是一个指向数据结构sockaddr的指针
                            其中包括客户端需要连接的服务器的目的端口和IP地址以及协议类型。
                addrlen :表示第二个参数内容的大小,可以使用sizeof(sockaddr)    而获得。
    【返回值】 成功 0, 失败-1
                查看错误码errno:
                    EACCES :在AF_UNIX 协议中,使用路径名作为标识符。EACCES 表示目录不可写或者不可访问
                    EADDRINSE :用户没有设置广播标志而连接广播地址或者连接请求被防火墙限制
                    EADDRINUSE :本地地址已经在使用
                    EAFNOSUPPORT :参数serv_addr的域sa_family不正确
                    EAGAIN :本地端口不足
                    EALREADY :socket 是非阻塞类型并且前面的连接没有返回
                    EBADF :文件描述符不是合法的值
                    ECONNREFUSED :连接的主机地址没有侦听
                    EFAULT :socket 是非阻塞模式,而连接不能立刻返回。
                    EINPROGRESS :socket 是非阻塞模式,而连接不能立刻返回
                    EINTR :函数被信号中断
                    EISCONN :socket 已经连接
                    ENETUNREACH :网络不可达
                    ENOTSOCK :文件描述符不是一个socket
                    ETIMEDOUT :连接超时
                    


6. send()通过套接字socket传输数据

【原型】    ssize_t send (int s,const void *msg,size_t len,int flags);
    【头文件】 #include < sys/socket.h >
    【功能】    将数据由指定的 socket 传给对方主机。
    【参数】    s :指定发送端套接字描述符;
                msg :要发送数据的缓冲区;
                len :指明实际要发送的数据的字符数;
                flags : 一般置0
                flags 参数有如下的选择:
                    MSG_DONTROUTE 勿将数据路由出本地网络
                    MSG_DONTWAIT 允许非阻塞操作(等价于使用O_NONBLOCK)
                    MSG_EOR 如果协议支持,此为记录结束
                    MSG_OOB 如果协议支持,发送带外数据
                    MSG_NOSIGNAL 禁止向系统发送异常信息
    【返回值】 成功:返回实际传送出去的字符数,失败返回-1,错误原因存于errno 中。
                错误代码errno:
                EBADF 参数 s 非法的 socket 处理代码。
                EFAULT 参数中有一指针指向无法存取的内存空间。
                WNOTSOCK 参数 s 为一文件描述词,非 socket。
                EINTR 被信号所中断。
                EAGAIN 此动作会令进程阻断,但参数 s 的 socket 为不可阻断的。
                ENOBUFS 系统的缓冲内存不足。
                EINVAL 传给系统调用的参数不正确。
                

    【函数说明】
                1. send() 使用 send 时套接字必须已经连接。
                2. send 不包含传送失败的提示信息,如果检测到本地错误将返回-13. 如果send 成功返回,并不必然表示连接另一端的进程接收数据。
                   所保证的仅是当send 成功返回时,数据已经无错误地发送到网络上。
                4. 对于支持为报文设限的协议,如果单个报文超过协议所支持的最大尺寸,
                   send 失败并将 errno 设为 EMSGSIZE ;对于字节流协议,send 会阻塞直到整个数据被传输。
                   
      



7. recv()通过套接字接收数据

    【原型】    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    【头文件】 #include <sys/types.h>
                #include <sys/socket.h>
    【功能】    接收客户端消息
    【参数】    sockfd : 接收端套接字描述符; 
                buf:    指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据; 
                len :   buf的长度; 
                flags: 第四个参数一般置0。
    【返回值】 成功:返回接收到的字节数。另一端已关闭则返回0
                失败返回-1,
                错误码errno: 
                EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时 
                EBADF:sock不是有效的描述词 
                ECONNREFUSE:远程主机阻绝网络连接 
                EFAULT:内存空间访问出错 
                EINTR:操作被信号中断 
                EINVAL:参数无效 
                ENOMEM:内存不足 
                ENOTCONN:与面向连接关联的套接字尚未被连接上 
                ENOTSOCK:sock索引的不是套接字 当返回值是0时,为正常关闭连接;
    
    【函数说明】
                1. recv先等待s的发送缓冲中的数据被协议传送完毕,
                    如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,
                2. 如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,
                3. 如果s接收缓冲区中没有数据或者协议正在接收数 据,那么recv就一直等待,直到协议把数据接收完毕。
                4. 当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中
                5. 协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。
                6. recv函数仅仅是copy数据,真正的接收数据是协议来完成的), recv函数返回其实际copy的字节数。
                7. 如果recv函数在等待协议接收数据时网络中断了,那么它返回08. 默认 socket 是阻塞的 解阻塞与非阻塞recv返回值没有区分,都是 <0 出错 =0 连接关闭 >0 接收到数据大小,
                9. 返回值<0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收。
                10. 只是阻塞模式下recv会阻塞着接收数据,非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要循环读取)。

          


8. htonl()、htons()大小端字节序转换主机到网络

    
    【原型】    uint32_t htonl(uint32_t hostlong);
                uint16_t htons(uint16_t hostshort);
    【头文件】 #include <arpa/inet.h>
    【功能】    htonl :主机字节序到网络字节序的长整型转换
                htons :主机字节序到网络字节序的短整型转换
    【参数】    hostlong、hostshort:需要转换的变量
    【返回值】 转换后的值




9. ntohl()、ntohs()大小端字节序转换网络到主机

    【原型】    uint32_t ntohl(uint32_t netlong);
                uint16_t ntohs(uint16_t netshort);
    【头文件】 #include<arpa/inet.h>
    【功能】    ntohl:网络字节序到主机字节序的长整型转换
                ntohs:网络字节序到主机字节序的短整型转换
    【返回值】 转换后的值



10. inet_aton()将点分十进制的IP地址转换为二进制IP地址

    【原型】int inet_aton(const char *cp, struct in_addr *inp);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    将cp中存储的点分十进制字符串类型的IP地址转换为
                二进制的IP地址
    【参数】    cp: 点分十进制字符串类型的IP地址
                inp: 指向的结构struct in_addr中。
    【返回值】 成功:非0 失败 0
    
    
   

11. inet_addr()将点分十进制的IP地址转换为二进制IP地址

   【原型】in_addr_t inet_addr(const char *cp);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    将cp中存储的点分十进制字符串类型的IP地址转换为
                二进制的IP地址,IP地址是以网络字节序表达。
    【参数】    cp: 点分十进制字符串类型的IP地址
    【返回值】 成功:转换后的IP地址 失败 -1 
     

12. inet_network()将点分十进制的IP地址转换为二进制IP地址

 【原型】in_addr_t inet_network(const char *cp);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    将cp中存储的点分十进制字符串类型的IP地址转换为
                二进制的IP地址,IP地址是以网络字节序表达的
    【参数】    cp:采用如下形式:
                (1) a.b.c.d : 完全的IP地址转换,此情况下与inet_addr()完全一致
                (2) a.b.c :这种形式指定了IP地址的前3个段,a.b解释为IP地址的前16位
                    c解释为IP地址的后16(3) a.b: 这种形式指定了IP地址的前2个段,a为IP地址的前8,b解释为后面的24位
                        例如:172.888888 会将888888解释为IP地址的后3(4) a:当仅为一部分时,a的值直接作为IP地址,不做字节序转换。
    【返回值】 成功:返回32位表示IP地址 失败 -1
    
    

13. inet_ntoa()将一个地址结构转换为点分十进制的IP地址

    【原型】char *inet_ntoa(struct in_addr in);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    将一个参数in所表示的Internet地址结构转换为点分十进制的
                4 段式字符串IP地址 形式:a.b.c.d
    【参数】    in :Internet地址结构
    【返回值】 成功:转换后的字符串指针 
    【注意】    转换后的字符串指针内存区域为静态的,有可能被覆盖,因此函数并不是线程安全。

14. inet_makeaddr()将网络地址和主机地址合并成IP地址

  【原型】 struct in_addr inet_makeaddr(int net, int host);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    将主机字节序的网络地址net和主机地址host合并成一个网络字节序的IP地址
    【参数】    net :网络地址   
                host :主机地址
    【返回值】 成功:合并成的网络字节序的IP地址


15. inet_lnaof()返回IP地址的主机部分


    【原型】  in_addr_t inet_lnaof(struct in_addr in);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    返回IP地址的主机部分
    【参数】    in : IP地址
    【返回值】 成功:IP地址的主机部分。

16. inet_netof()返回IP地址的网络部分

   【原型】  in_addr_t inet_netof(struct in_addr in);
    【头文件】  #include <netinet/in.h>
                 #include <arpa/inet.h>
    【功能】    返回IP地址的网络部分
    【参数】    in : IP地址
    【返回值】 成功:IP地址的网络部分。 

17. inet_pton()将IP地址转换为二进制类型

    【原型】    int inet_pton(int af, const char *src, void *dst);
    【头文件】 #include <arpa/inet.h>
    【功能】    将字符串类型的IP地址转换为二进制类型
    【参数】    af : 网络类型的协议族,在IPv4下的值为:AF_INET
                src :需要转换的字符串
                dst:指向转换后的结果指针
    【返回值】 成功:正值 失败:
                                0 :src指向的值不是合法的IP地址
                                -1 :通常是af所指定的协议族不支持
                                    此时返回错误码errno :EAFNOSUPPORT

18. inet_ntop()将二进制网络IP地址转换为字符串


    【原型】    int inet_ntop(int af, const char *src, char *dst,socklen_t cnt);
    【头文件】 #include <arpa/inet.h>
    【功能】    将二进制网络IP地址转换为字符串
    【参数】    af : 网络类型的协议族,在IPv4下的值为:AF_INET
                src :需要转换的二进制IP地址 
                在IPv4下src指向struct in_addr结构类型的指针
                dst:指向保存结果缓冲区的指针 
                cnt :是dst缓冲区的大小
    【返回值】 成功:指向dst的指针 
                失败:NULL
                errno :EAFNOSUPPORT :af设定的协议族不支持
                errno :ENOSPC :dst缓冲区大小过小。
                                    
       


19. setsockopt()设置套接字关联的选项

    【原型】    int setsockopt(int socket, int level, int option_name,
                            const void *option_value, socklen_t option_len);
    【头文件】 #include <sys/types.h>
                #include <sys/socket.h>
    【参数】
            1. socket:将要被设置或者获取选项的套接字。
            2. level:选项所在的协议层。
                (1)SOL_SOCKET:通用套接字选项.
                (2)IPPROTO_IP:IP选项.
                (3)IPPROTO_TCP:TCP选项.
            3. option_name:需要访问的选项名。
            
                选项名称        说明                  数据类型
                ========================================================================
                            SOL_SOCKET
                ------------------------------------------------------------------------
                SO_BROADCAST      允许发送广播数据            int
                SO_DEBUG        允许调试                int
                SO_DONTROUTE      不查找路由               int
                SO_ERROR        获得套接字错误             int
                SO_KEEPALIVE      保持连接                int
                SO_LINGER        延迟关闭连接              struct linger
                SO_OOBINLINE      带外数据放入正常数据流         int
                SO_RCVBUF        接收缓冲区大小             int
                SO_SNDBUF        发送缓冲区大小             int
                SO_RCVLOWAT       接收缓冲区下限             int
                SO_SNDLOWAT       发送缓冲区下限             int
                SO_RCVTIMEO       接收超时                struct timeval
                SO_SNDTIMEO       发送超时                struct timeval
                SO_REUSERADDR      允许重用本地地址和端口         int
                SO_TYPE         获得套接字类型             int
                SO_BSDCOMPAT      与BSD系统兼容              int
                ========================================================================
                            IPPROTO_IP
                ------------------------------------------------------------------------
                IP_HDRINCL       在数据包中包含IP首部          int
                IP_OPTINOS       IP首部选项               int
                IP_TOS         服务类型
                IP_TTL         生存时间                int
                ========================================================================
                            IPPRO_TCP
                ------------------------------------------------------------------------
                TCP_MAXSEG       TCP最大数据段的大小           int
                TCP_NODELAY       不使用Nagle算法             int
                ========================================================================
                
            4. option_value:指向包含新选项值的缓冲。
            5. option_len:现选项的长度。
            
    【功能】    获取或者设置与某个套接字关联的选 项。
                选项可能存在于多层协议中,它们总会出现在最上面的套接字层。
                当操作套接字选项时,选项位于的层和选项的名称必须给出。
                为了操作套接字层的选项,应该 将层的值指定为SOL_SOCKET。
                为了操作其它层的选项,控制选项的合适协议号必须给出。
                例如,为了表示一个选项由TCP协议解析,层应该设定为协议 号TCP。
            
    【返回值】  成功:0。失败:-1
                errno被设为以下的某个值:  
                EBADF:sock不是有效的文件描述词
                EFAULT:optval指向的内存并非有效的进程空间
                EINVAL:在调用setsockopt()时,option_len无效
                ENOPROTOOPT:指定的协议层不能识别选项
                ENOTSOCK:sock描述的不是套接字
                
    【注意点】 当设置TCP套接口接收缓冲区的大小时,函数调用顺序是很重要的,
                因为TCP的窗口规模选项是在建立连接时用SYN与对方互换
                得到的。对于客户,O_RCVBUF选项必须在connect之前设置;
                对于服务器,SO_RCVBUF选项必须在listen前设置。



20. getsockopt()获得套接字关联的选项

    【原型】     int getsockopt(int socket, int level, int option_name,
                                void *restrict option_value, socklen_t *restrict option_len);
                                
    【参数】optval:指向返回选项值的缓冲。
            optlen:作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。
            
    【其他值参照setsockopt】

21. sendto()把UDP数据报发给指定地址


    【原型】    ssize_t sendto(int socket, const void *message, size_t length,
                            int flags, const struct sockaddr *dest_addr,
                            socklen_t dest_len);
                            
    【头文件】 #include <sys/socket.h>
    
    【参数】    (1)socket:  正在监听端口的套接口文件描述符
                (2)message: UDP数据报缓存地址。(发送数据缓冲区)
                (3)lenght:  UDP数据报长度。(发送数据缓冲区大小)
                (4)flags:   该参数一般为0(5)dest_addr:      struct sockaddr_in类型,指明UDP数据发往哪里报。
                (6)dest_len:   对方地址长度,一般为:sizeof(struct sockaddr_in)。
                
    
    【返回值】 成功:返回实际传送出去的字符数
                失败返回-1 :错误原因存于errno 中。
				errno:
                EBADF 参数s非法的socket处理代码。
                EFAULT 参数中有一指针指向无法存取的内存空间。
                ENOTSOCK 参数 s为一文件描述词,非socket。
                EINTR 被信号所中断。
                EAGAIN 此动作会令进程阻断,但参数s的socket为不可阻断的。
                ENOBUFS 系统的缓冲内存不足。
                EINVAL 传给系统调用的参数不正确。

            

22. recvfrom()从指定地址接收UDP数据报

    【原型】    ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
                                int flags, struct sockaddr *restrict address,
                                socklen_t *restrict address_len);
                                
    【头文件】  #include <sys/socket.h>
    
    【参数】    (1)socket:  socket描述符。
                (2)buffer: UDP数据报缓存地址。
                (3)lenght:  UDP数据报长度。
                (4)flags:   该参数一般为0(5)address: struct sockaddr_in类型,指向本地的数据结构体sockaddr_in的指针,
                            发送数据时发送方的地址信息放在这个结构体中。
                (6)address_len  表示address所指内容的长度,可以使用sizeof(struct sockaddr_in)来获得。
                
    【返回值】 成功:返回收到的数据长度,数据长度可以为0
                失败:返回-1
                发生错误的errno:
				EBADF 参数s非合法的socket处理代码
                EFAULT 参数中有一指针指向无法存取的内存空间。
                ENOTSOCK 参数s为一文件描述词,非socket。
                EINTR 被信号所中断。
                EAGAIN 此动作会令进程阻断,但参数s的socket为不可阻断。
                ENOBUFS 系统的缓冲内存不足
                ENOMEM 核心内存不足
                EINVAL 传给系统调用的参数不正确。


19-21-22代码演示:

————————————————————————————————————————————————————————————

客户端:

#include "myhead.h"//这个头文件里面已经将常用函数的头文件全部包含了
/*
   演示udp广播发送端
*/
int main()
{
    int udpsock;
    int ret;
    char buf[20];
    struct sockaddr_in destaddr;
    bzero(&destaddr,sizeof(destaddr));
    destaddr.sin_family=PF_INET;
    destaddr.sin_port=htons(10000);
    //使用广播地址
    inet_aton("192.168.110.255",&(destaddr.sin_addr));
    
    udpsock=socket(PF_INET,SOCK_DGRAM,0);//创建数据报套接字
    if(udpsock==-1)
    {
        perror("创建udp失败!\n");
        return -1;
    }
    //设置套接字的属性为可以广播
    int on = 1;
    ret=setsockopt(udpsock,SOL_SOCKET,SO_BROADCAST, &on, sizeof(on));
    if(ret==-1)
    {
        perror("设置广播失败!\n");
        return -1;
    }
    //广播发送信息 
    bzero(buf,20);
    printf("请输入你要广播发送的内容!\n");
    fgets(buf,20,stdin);
    ret=sendto(udpsock,buf,20,0,(struct sockaddr *)&destaddr,sizeof(destaddr));
    printf("sendto返回值是:%d\n",ret);
}


服务端:


#include "myhead.h"//这个头文件里面已经将常用函数的头文件全部包含了
/*
   演示udp广播接收端
*/
int main()
{
    int udpsock;
    int ret;
    int addrsize=sizeof(struct sockaddr);
    char buf[20];
    struct sockaddr_in bindaddr;
    struct sockaddr_in souraddr;
    bzero(&bindaddr,sizeof(bindaddr));
    bindaddr.sin_family=PF_INET;
    bindaddr.sin_port=htons(10000);
    bindaddr.sin_addr.s_addr=htonl(INADDR_ANY);//注意
    
    udpsock=socket(PF_INET,SOCK_DGRAM,0);//创建数据报套接字
    if(udpsock==-1)
    {
        perror("创建udp失败!\n");
        return -1;
    }
    //绑定
    ret=bind(udpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
    if(ret==-1)
    {
        perror("绑定失败!\n");
        return -1;
    }
    //接收信息 
    bzero(buf,20);
    ret=recvfrom(udpsock,buf,20,0,(struct sockaddr *)&souraddr,&addrsize);
    printf("recvfrom返回值是:%d  %s\n",ret,buf);
}


————————————————————————————————————————————————————————————




   

23. select()监视文件描述符的状态

    【原型】    int select(int nfds, fd_set *restrict readfds,
                          fd_set *restrict writefds, fd_set *restrict errorfds,
                          struct timeval *restrict timeout);
                          
    【头文件】 #include <sys/select.h>
    【功能】    监视多个文件描述符的集合,判断是否有符合条件的时间发生。
    
    【参数】    nfds: 比所有文件描述符集合中的文件描述符的最大值大1的变量
                readfds :监测文件描述符集合中的任意一个文件是否有数据可读。
                writefds: 监测文件描述符集合中的任意一个文件是否有数据可写。
                errorfds : 监测文件集中的任何文件是否发生错误
                timeout : 超时等待时间(最长的等待时间),当超过此时间时,函数会返回。
                struct timeval
                        {
                            time_t tv_sec;  /*秒*/
                            long tv_usec;   /*微秒*/
                        };
                
    【返回值】 1. 超时返回 0
                2. 文件描述符符合要求 :返回大于 0 的正值
                        (1)读文件描述符集中的文件可读
                        (2)写文件描述符集中的文件可写
                        (3)错误文件描述符中的文件发生错误
                        
                3. 返回值为 -1 :发生了错误,错误码errno如下:
                        (1) EBADF :参数s不是合法描述符
                        (2) EINTR :接收到中断信号
                        (3) EINVAL : 传递了不合法参数
                        (4) ENOMEM :没有足够内存
                
                
    【注意点】 1. nfds在使用之前必须计算最大值的文件描述符的值,才能将其值写入进nfds
                2. readfds 当select()函数返回的时候,将清除其中不可读的文件描述符,只留下可读的文件描述符
即可以被recv(),read()等进行数据的操作。
                3. writefds 当select()函数返回的时候,readfds将清除其中的不可写的文件描述符,只留下可写的文件描述符
即可以被send()write()函数等进行写数据的操作。
                4. errorfds还可以监视外数据OOB,当select函数返回的时候,readfds将清除其中的其他文件描述符,只留下可读OOB数据
                5. 当 timeout 设置为NULL的时候,表示阻塞操作,会一直等待,直到某个监视的文件集中的某个文件描述符符合返回条件。
                   当timeout为0的时候,函数会立即返回
                   
                6. 函数select()允许程序监视多个文件描述符,当一个或者多个文件描述符准备就绪,可以进行IO操作的时候返回。
    
    
    【返回值】 1. 超时返回 0
                2. 文件描述符符合要求 :返回大于 0 的正值
                        (1)读文件描述符集中的文件可读
                        (2)写文件描述符集中的文件可写
                        (3)错误文件描述符中的文件发生错误
                        
                3. 返回值为 -1 :发生了错误,错误码errno如下:
                        (1) EBADF :参数s不是合法描述符
                        (2) EINTR :接收到中断信号
                        (3) EINVAL : 传递了不合法参数
                        (4) ENOMEM :没有足够内存

                        
                      

24. pselect()监听文件描述符的状态

   【原型】    int pselect(int nfds, fd_set *restrict readfds,
                              fd_set *restrict writefds, fd_set *restrict errorfds,
                              const struct timespec *restrict timeout,
                              const sigset_t *restrict sigmask);

                          
    【头文件】 #include <sys/select.h>
    【功能】    监视多个文件描述符的集合,判断是否有符合条件的时间发生。
    
    
    【参数】    nfds: 比所有文件描述符集合中的文件描述符的最大值大1的变量
                readfds :监测文件描述符集合中的任意一个文件是否有数据可读。
                writefds: 监测文件描述符集合中的任意一个文件是否有数据可写。
                errorfds : 监测文件集中的任何文件是否发生错误
                timeout : 超时等待时间(最长的等待时间),当超过此时间时,函数会返回。
                    struct timeval
                            {
                                long tv_sec;        /*超时的秒数*/
                                long tv_nsec;       /*超时纳秒数*/
                            };
                signask :替换掉的信号处理方式,为NULL与select一样。
                


25. FD文件描述符号集的操作宏(并非函数)

    【宏1void FD_CLR(int fd, fd_set *fdset);
      【功能】  用来将一个给定的文件描述符从集合中删除
    
      【宏2int FD_ISSET(int fd, fd_set *fdset);
      【功能】  检测fd在sdset集合中的状态是否变化,当检测到状态发生变化的时候返回真(0),否则返回假0
      【返回值】   真:非0 
                    假: 0
      【宏3void FD_SET(int fd, fd_set *fdset);
      【功能】  用来将一个给定的文件描述符加入集合中
      
      【宏4void FD_ZERO(fd_set *fdset);
      【功能】  用来清空fd_set集合。
      
      【参数】  fd :文件描述
                fdset :文件描述符集。
      

26. poll() 等待某个文件描述符上的某个事件的发生

    【原型】    int poll(struct pollfd *fds,nfds_t nfds,int timeout);
    【头文件】 #include <poll.h>
    【功能】    检测文件描述符的状态
    【参数】    (1) fds :是一个数组,存放的是一组要监测的文件描述符
                (2) nfds :是比监视的最大描述符的值大1的值
                (3) timeout :是超时时间,单位为毫秒,当为负值的时表示永远等待。
                struct pollfd
                {
                    int fd; //文件描述符
                    short event; //请求的时间
                    short revents; //返回的事件 
                }
                event与revents的监视事件
                POLLIN:有数据到来,文件描述符可读
                POLLPRI :有紧急数据可读,例如带外数据
                POLLOUT : 文件可写
                POLLRDHUP : 流式套接字半关闭
                POLLERR : 错误发生
                POLLHUP :关闭
                POLLNVAL : 非法请求
                POLLRDNORM : 与POLLIN相同
                POLLRDBAND :优先数据可读
                POLLWRNORM : 与POLLOUT 相同
                POLLWRBAND : 优先数据可写
                
    【返回值】 成功:大于0 (等待的某个条件满足,返回值为满足条件的监视文件描述符的数量)
                失败: 0 表示超时
                       -1; 表示发生错误,errno的错误代码表:
                        EBADF:参数S不是合法描述符
                        EINTR: 接收到中断信号 
                        EINVAL: 传递了不合法的参数
                        ENOMEM: 没有足够内存