网络编程函数

 
一、网络字节序     
       网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。
       主机字节序就是我们平常说的大端和小端模式:不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序 这个叫做主机序。
    由于每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器,一定要对数据进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字节顺序相同,也应该在传输数据以前先调用数据转换函数,以便程序移植到其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。所以在传输多字节整形数时,需要将其转换为网络字节序。
有关的转换函数
uint16_t htons(uint16_t hostshort);
主机字节顺序转换成网络字节顺序,对无符号短型进行操作
uint32_t htonl(uint32_t hostlong);
主机字节顺序转换成网络字节顺序,对无符号长型进行操作

以上函数的参数就是本地主机序的整数。返回值是:TCP/IP网络字节序

uint16_t ntohs(uint16_t netshort);
网络字节顺序转换成主机字节顺序,对无符号短型进行操作
uint32_t ntohl(uint32_t netlong);
网络字节顺序转换成主机字节顺序,对无符号长型进行操作
注:以上函数原型定义在netinet/in.h里

int inet_aton(const char *cp, struct in_addr *inp);
        功能:将一个字符串IP地址转换为一个32位的网络序列IP地址。
        参数:
                 cp:点分十进制的字符串IP地址
                 inp:存放转换好的32位网络字节序
        返回值:成功返回非0值,如果地址不正确会返回0.并不设置errno

char *inet_ntoa(struct in_addr in);
        功能:将32位的网络字节序转换为字符串IP地址
        参数:
                 in:32位网络字节序IP地址。
        返回值:成功返回指向字符串的指针。错误,返回NULL。
        注:inet_aton和inet_ntoa仅适用于IPV4协议

int inet_pton(int af, const char *src, void *dst);
       功能:将一个字符串IP地址转换为一个网络序列IP地址
参数:
              af:AF_INET :需要转换的得IPV4地址,函数将该地址转换为in_addr的结构体
                     AF_INET6:需要转换的是IPV6地址,函数将该地址转换为in6_addr的结构体
              src:字符串IP地址
              dst:存放转换好的IP地址
        返回值:成功返回1,当src为无效值时,返回-1,当af为无效值时,返回0;

const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
       功能:将网络字节序地址转换为字符串IP地址
       参数:
                af:AF_INET :需要转换的得IPV4地址,函数将该地址转换为in_addr的结构体
                      AF_INET6:需要转换的是IPV6地址,函数将该地址转换为in6_addr的结构体
                src:网络字节序IP地址
                dst:存放转换好的字符串IP地址
size:是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针
      返回值:成功返回一个指向dst的非空指针,失败返回一个NULL

二、其他函数:
网络编程的一些结构体:
     struct sockaddr {
             unsigned short  sa_family;      是2字节的地址家族,一般都是“AF_xxx”的形式。
           char            sa_data[14];     sa_data : 是14字节的协议地址。
  };
由于上面的通用结构体易用性不是很好,所以一般使用下面的结构体。
struct sockaddr_in {
  short int sin_family;      指代协议族
  unsigned short int sin_port;      存储端口号(使用网络字节顺序)
  struct in_addr sin_addr;        存储IP地址,使用in_addr这个数据结构
  unsigned char sin_zero[8];     是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
  };
typedef struct in_addr {
 unsigned long s_addr;       用一个长整型来表示IP地址。

int socket(int domain, int type, int protocol);
        功能:创建一个套接字
        参数:
                domain:AF_INET:   IPV4协议
                                 AF_INET6:IPV6协议
                                 AF_LOCAL: Unix域协议
                                 AF_ROUTE:路由套接口
                                AF_KEY:密钥套接口
                type:SOCK_STREAM:字节流套接口  ,面向连接的,可靠地字节流。TCP协议
                        SOCK_DGRAM:数据报套接口,无连接的不可靠报文传递。UDP协议
                        SOCK_RAW:原始套接口,IP协议的数据报接口,需要超级用户权限。绕过TCP,UDP传输协议。
              protocol:一般为0,当使用原始套接字时除外。
       返回值:成功返回一个新的套接字描述符,失败返回-1.

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        功能将一本地地址与一套接口捆绑
        参数:
                 sockfd 表示已经建立的socket编号(描述符)
 addr: 是一个指向sockaddr结构体类型的指针;如果只为INADDR_ANY,套接字可以被绑定到系统的任一可用的网络地址,这意味着可以收到这个系统所安装的所有网卡的数据包。
    
    
                     addrlen:表示struct sockaddr结构的长度,可以用sizeof函数获得。
        返回值:成功返回0,失败返回-1;
注:端口号一般不要小于5000,当端口设置为0时, 随机选择一个没有使用的端口。当使用INADDR_ANY时,这时bind其实并没有绑定。 

int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        功能:用于获取一个已绑定到套接字的地址(IP地址和端口号等)
        参数:
                   sockfd:套接字描述符
                   addr:将返回的地址放到addr中。
addrlen:该数在调用函数以前被设置为struct sockaddr的长度,当函数返回时,该数会被设为struct sockaddr的大小,如果两者不匹配,则将其截短不报错。
        返回值:成功返回0,出错返回-1
注:如果当前套接字没有绑定任何地址,则其结果没有定义。 若一个套接口与INADDR_ANY捆绑,也就是说该套接口可以用任意主机的地址,此时除非调用connect()或accept()来连接,否则getsockname()将不会返回主机IP地址的任何信息

int   getpeername(int   sockfd,  struct  sockaddr  *addr,socklen_t *addrlen);
        功能:若套接字已经和对方连接,获得对方的地址(IP地址和端口号等)
        参数:
     
     
                   sockfd:套接字描述符
                   addr:将返回的地址放到addr中。
    
    
addrlen:该数在调用函数以前被设置为struct sockaddr的长度,当函数返回时,该数会被设为struct sockaddr的大小,如果两者不匹配,则将其截短不报错。

      返回值:成功返回0,出错返回-1
     注:该套接字必须已与一个地址连接,否则返回不确定。

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        功能:在使用面向连接的网络服务以前,需在客户端和服务器端建立一个连接,可以使用connect来建立连接
        参数:
                sockfd: 套接字文件描述符
                addr: 要连接的目的地址
                addrlen:struct sockaddr的长度
     返回值:成功返回0,失败返回-1
注:
    
    
  • 如果sockfd并没有绑定到一个地址,connect会给调用者绑定一个默认地址。如果connect失败,则套接口不可再用,必须关闭,不能在对此套接口调用connect。必须关闭后,重新调用socket创建一个套接口
  •  connect还可以用于无连接的网络服务,如果在SOCK_DGRAM套接字上调用connect,所有发送报文的目标地址设为connect调用中所指定的地址,这样,每次在传送报文时,就不需要再提供地址。另外,仅能接受来自指定地址的报文。

int listen(int sockfd, int backlog);
        功能:设置可以监听最大连接请求,包括已连接的和未连接的
        参数:
                    sockfd:套接字描述符
                    backlog:最大连接请求数
        返回值:成功返回0,失败返回-1
注:当socket创建一个套接口时,它被假设为一个主动接口,也就是说,他是一个将调用connect发起连接的客户套接口,函数listen将未连接的套接口转换成被动套接口,只是内核应接受向此套接口的连接请求。调用listen导致套接口从CLOSED状态转换到LISTEN状态。一旦调用了listen,套接字就能接受连接请求。
不要将backlog定义为0,一位不同实现对此有不同解释,有些实现容许有一个连接排队,有的则不容许有连接排队。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        功能:等待接受连接请求。
        参数:
                    sockfd:套接字描述符
                    addr:用来存放返回的客户端地址
addrlen:在此函数调用前,将addrlen设置为addr所指向的套接字地址结构的长度。当此函数返回后,此数便被设置成由内核定义的此套接字地址结构的准确长度。
返回值:成功返回一个新的套接字描述符,该描述符连接到调用connect的客户端,这个新的描述符合原始套接字(sockfd)具有相同的套接字类型和地址族。以后对连接的客户端操作时,便使用这个新的描述符。失败返回-1.
          注:如果当前没有未完成的连接请求,则此函数睡眠阻塞。如果sockfd处于非阻塞模式下,则会返回-1。因为一般情况下服务器创建的sockfd 还要用于接收其它客户端的连接请求。所以accept要返回一个新的描述符。而sockfd继续等待别的连接请求。而connect用于客户端,一般只与一个服务器连接,所以不返回一个新的描述符

三、数据传送函数
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
            功能:发送数据
            参数:
                      sockfd:套接字描述符
                      buf:待发送数据的缓冲区
                      len:要发送的数据长度
                     flags:
                        MSG_OOB 发送带外数据。
                        MSG_DONTROUTE 勿将数据路由出本地网络
MSG_DONTWAIT 允许非阻塞操作
        返回值:成功则返回实际传送出去的字符数,失败返回-1
        注:使用send时,套接字必须是已连接的,因为send不知道要将数据发送何处。当套接字输出队列没有足够的空间来发送消息时,send会阻塞,同样适用于下列两个函数sendto和sendmsg。但当套接字在非阻塞模式下士时,情况会改变,在这种情况下,这些函数不会阻塞而是失败。


ssize_t sendto(int  sockfd, const void *buf, size_t len, int  flags,const struct sockaddr *dest_addr, socklen_t  addrlen);
            功能:发送数据
            参数:
                     sockfd:套接字描述符
      
      
           buf:待发送数据的缓冲区
           len:要发送的数据长度
           flags:
    
    
   MSG_OOB 发送带外数据。
    
    
   MSG_DONTROUTE 勿将数据路由出本地网络
    
    
   MSG_DONTWAIT 允许非阻塞操作
          dest_addr:将要发送的目标地址
          addrlen:struct sockaddr的长度
      返回值:成功则返回实际传送出去的字符数,失败返回-1

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
            功能:发送数据
            参数:
        sockfd:套接字描述符
        msg:
             struct msghdr {
                                            void         *msg_name;
                                            socklen_t    msg_namelen;
                                           struct iovec *msg_iov;
                                            size_t       msg_iovlen;
                                            void         *msg_control;
                                            size_t       msg_controllen;
                                            int          msg_flags;
                                };
        flags:
MSG_OOB 发送带外数据。
MSG_DONTROUTE 勿将数据路由出本地网络
MSG_DONTWAIT 允许非阻塞操作
        返回值:成功则返回实际传送出去的字符数,失败返回-1
     注:
      
      
  • 对于以上三个函数,当套接字输出队列没有足够的空间来发送消息时,则会一直阻塞。但当套接字在非阻塞模式下时,情况会改变,在这种情况下,这些函数不会阻塞而是失败。
  • 如果调用shutdow关闭了读端或者服务器端进程关闭socket以后,则当前进程收到一个SIGPIPE信号,终止进程
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
     
     
      功能:接收数据
      参数:
                   sockfd: 套接字描述符
                   buf:         接收数据的缓冲区
                   len:          要接收的数据长度
                   flags:
                MSG_OOB 接收带外数据。
     
     
MSG_DONTWAIT 允许非阻塞操作
     
     
MSG_TRUNC  一般数据被截断
     
     
MSG_TRUNC  控制数据被截断
     
     
MSG_TRUNC  控制数据被截断
     
     
MSG_EOR  接收到记录结束符
             返回值:成功返回读到的字节数,失败返回-1.
注:如果调用shutdow关闭了发送端,则当所有数据接收完毕后,返回0;当客户端进程关闭时,ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
    
    
     功能:接收数据
     参数:
                   sockfd:   套接字描述符
                     buf:       接收数据的缓冲区
                     len:       要接收的数据长度
flags:
     
     
    MSG_OOB 接收带外数据。
MSG_DONTWAIT 允许非阻塞操作
MSG_TRUNC 一般数据被截断
MSG_TRUNC 控制数据被截断
MSG_EOR 接收到记录结束符
    
    
src_addr:将返回的发送者地址存放在src_addr中。
addrlen:在此函数调用前,将addrlen设置为addr所指向的套接字地址结构的长度。当此函数返回后,此数便被设置成由内核定义的此套接字地址结构的准确长度。

          返回值:成功返回读到的字节数,失败返回-1.

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
        功能:接收数据
    
    
        
        
    参数:
                sockfd:套接字描述符
                  msg:
                          struct msghdr {
                                            void         *msg_name;
                                            socklen_t    msg_namelen;
                                           struct iovec *msg_iov;
                                            size_t       msg_iovlen;
                                            void         *msg_control;
                                            size_t       msg_controllen;
                                            int          msg_flags;
                                };
              flags:
                        MSG_OOB 接收带外数据。
                    MSG_DONTWAIT 允许非阻塞操作
                    MSG_TRUNC  一般数据被截断
                    MSG_TRUNC  控制数据被截断
                    MSG_EOR  接收到记录结束符
        返回值:成功返回读到的字节数,失败返回-1.
注:
    
    
  • 当服务器的sockfd和地址绑定以后,以上三个recv函数,可以接受任何向此地址发送数据的连接,并没有指定要接受的地址。
  • 以上三个函数当为阻塞模式下时,如果没有数据可读,则阻塞。如果调用shutdow关闭了发送端或者客户端进程关闭socket以后,则当所有数据接收完毕后,返回0;
  
  

四、套接字选项:
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
        功能:获得套接字的选项(属性)
        参数:
                    socket:套接字描述符   
                    level:选项所在的协议层。见下表1.1
                    optname:选项名称,见下表1.1
                    optval:将获得的相应选项的开关状态存放在optval中,如果为0,表示此选项关闭,非0,表示此选项被启用。
                                optval必须指向每个选项的数据类型。
                    optlen:optval 的大小
     返回值:成功返回0,出错返回-1


int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
            功能:设置一个套接字的选项(属性)
           参数:
                   socket:套接字描述符
          level:选项所在的协议层。见下表1.1
         optname:选项名称,见下表1.1
                  optval:没有特殊说明时,默认为整形设置相应选项的开关状态,如果为0,表示要将此选项关闭,非0,表示要将此选项启用。如果为特殊说明结构,则需要按照结构设置。
            optval必须指向每个选项的数据类型。
         optlen:optval 的大小
返回值:成功返回0,失败返回-1.
      
      
                                                表1.1































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
网络编程是指使用计算机网络进行数据传输和通信的程序开发。在网络编程中,有许多常用的函数和工具可以帮助我们进行网络通信。下面是一些常见的网络编程函数的详细讲解: 1. socket() 函数:用于创建一个套接字(socket)。套接字是网络通信的基础,它可以用于发送和接收数据。socket() 函数的原型如下: ```c int socket(int domain, int type, int protocol); ``` - domain:指定套接字的地址族,常用的有 AF_INET(IPv4)和 AF_INET6(IPv6)。 - type:指定套接字的类型,常用的有 SOCK_STREAM(流式套接字,用于可靠的、面向连接的通信)和 SOCK_DGRAM(数据报套接字,用于不可靠的、无连接的通信)。 - protocol:指定套接字所使用的协议,一般设置为 0,表示使用默认协议。 2. bind() 函数:将一个套接字与特定的 IP 地址和端口号绑定。bind() 函数的原型如下: ```c int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ``` - sockfd:指定要绑定的套接字描述符。 - addr:指向一个 sockaddr 结构体,包含要绑定的 IP 地址和端口号。 - addrlen:指定 sockaddr 结构体的大小。 3. listen() 函数:将一个套接字设置为监听状态,等待客户端连接。listen() 函数的原型如下: ```c int listen(int sockfd, int backlog); ``` - sockfd:指定要监听的套接字描述符。 - backlog:指定同时等待连接的最大数量。 4. accept() 函数:接受客户端的连接请求,创建一个新的套接字用于与客户端通信。accept() 函数的原型如下: ```c int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ``` - sockfd:指定要接受连接请求的套接字描述符。 - addr:用于保存客户端的地址信息。 - addrlen:指向一个整型变量,表示 addr 结构体的大小。 5. connect() 函数:与服务器建立连接。connect() 函数的原型如下: ```c int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ``` - sockfd:指定要连接的套接字描述符。 - addr:指向一个 sockaddr 结构体,包含要连接的服务器的 IP 地址和端口号。 - addrlen:指定 sockaddr 结构体的大小。 6. send() 和 recv() 函数:用于发送和接收数据。send() 函数用于发送数据,recv() 函数用于接收数据。它们的原型如下: ```c ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags); ``` - sockfd:指定要发送或接收数据的套接字描述符。 - buf:指向保存数据的缓冲区。 - len:指定要发送或接收的数据大小。 - flags:指定发送或接收数据的选项。 以上是一些常用的网络编程函数的详细讲解,它们在不同的网络编程场景中起着重要的作用。在实际开发中,还可以结合其他函数和技术,实现更复杂的网络通信功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值