UNP学习笔记(第三章:套接字编程简介)

来源:互联网 发布:php查询数据库并输出 编辑:程序博客网 时间:2024/04/17 03:31
本章开始讲解套接字API。

 

 

套接字地址结构

IPv4套接字地址结构

它以sockaddr_in命名,下面给出它的POSIX定义

struct in_addr{     in_addr_t s_addr;                    };stuct sockaddr_in{     uint8_t         sin_len;                           sa_family_t     sin_family;    /* AF_INET */     in_port_t       sin_port;            struct in_addr  sin_addr;     char            sin_zero[8];};

POSIX规范只需要这个结构中的3个字段:sin_family、sin_port和sin_addr。

下图列出了POSIX定义的关于socket编程的数据类型

 

通用的套接字地址结构

为了解决任意套接字地址结构都可以传递进使用套接字地址的套接字函数中,定义了一个通用的套接字地址结构。

任何套接字地址结构的指针都通过类型强制转换(变成通用套接字地址结构的指针)来做为函数参数。

通用的套接字地址结构如下所示

struct sockaddr{    uint8_t        sa_len;    sa_family_t    sa_family;                  char           sa_data[14];            };

 

IPv6套接字地址结构

struct in_addr{     in_addr_t     s_addr;                  };struct sockaddr_in{     uint8_t            sin_len;             sa_family_t        sin_family;       /* AF_INET6 */     in_port_t          sin_port;               struct in_addr     sin_addr;               char               sin_zero[8];        };

 

 

字节排序函数

网络字节序采用大端字节序,而不同主机使用不同的字节序。

下面4个函数用于主机字节序和网络字节序之间的相互转换

#include <netinet/in.h>uint16_t htons(uint16_t host16bitvalue);uint32_t htonl(uint32_t host32bitvalue);                                           //均返回:网络字节序的值;uint16_t ntohs(uint16_t net16bitvalue);uint32_t ntohl(uint32_t net32bitvalue);                                           //均返回:主机字节序的值;

h代表host,n代表network,s代表short,l代表long。

 

 

字节操纵函数

下面函数用于字节的设置、复制和比较。

#include <strings.h>void bzero(void *dest, size_t nbytes);void bcopy(const void *src, void *dest, size_t nbytes);void bcmp(const void *ptr1, const void *ptr2, size_t nbytes);                                     //返回:相等则为0,否则为非0
#include <string.h>void *memset(void *dest, int c, size_t nbytes);void *memcpy(void *dest, const void *src, size_t nbytes);int   memcmp(const void *s1, const void *s2, size_t nbytes);                                    //返回:相等则为0,否则为非0

 

 

函数inet_aton、inet_addr和inet_ntoa

这几个函数用于在点分十进制数串(如“206.168.112.96”)于它长度为32位的网络字节序二进制值间转换IPv4地址。

#include <arpa/inet.h>int_addr_t inet_addr(const char *strptr);                //已被舍弃,使用inet_aton函数代替int inet_aton(const char *strptr, struct in_addr *addrptr);                //返回:字符串有效返回1,否则为0char *inet_ntoa(struct in_addr inaddr);                //返回:指向一个点分十进制的字符串的指针

 

 

函数inet_pton和inet_ntop

相对于上面的几个函数,这两个函数对于IPv4地址和IPv6地址都适用

#include <arpa/inet.h>int inet_pton(int family, const char *strptr, void *addrptr);                                      //返回:若成功返回1,输入不是有效表达格式返回0,若出错返回-1const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);                                       //返回:若成功则返回指向结果的指针,出错则为NULL

p代表表达(presentation)  n代表数值(numeric)

family参数既可以是AF_INET,也可以是AF_INET6。

inet_pton尝试转换由strptr指针指向的字符串,并通过addrptr指针存放二进制结果。

inet_ntop进行相反的转换,len参数是目标储存单元的大小,以免该函数一处其调用者的缓冲区。对此,<netinet/in.h>头文件中由如下定义:

#define INET_ADDRSTRLEN            16              #define INET6_ADDRSTRLEN           46        

 

 

UNP中定义的几个函数

inet_ntop函数的一个基本问题是:要求调用者必须知道这个结构的格式和地址族

我们可以使用自己定义的sock_ntop函数来解决这个问题

#include "unp.h"char *sock_ntop(const struct sodkaddr *sockaddr, socklen_t addrlen);

该函数内部使用sockaddr指针来确定地址族,然后调用inet_ntop。

同样的,我们为操作套接字地址结构定义了如下几个函数

 

 

 

readn、writen和readline函数

字节流套接字(例如TCP套接字)上read和write函数所表现的行为不同于通常的文件

字节流套接字上调用read或write输入或输出的字节数可能比请求的数量少,然而这不是出错的状态,此时所需的是调用者再次调用read或write函数,以输入或输出剩余的字节。

我们提供一下3个函数是每当我们读或写一个字节流套接字时总要使用的函数

#include "unp.h"ssize_t readn(int filedes,void *buff,size_t nbytes);ssize_t writen(int filedes,const void *buff,size_t nbytes);ssize_t readline(int filedes,void *buff,size_t nbytes);                          //返回值:读或写的字节数,若出错则为-1

readn实现代码

 1 #include "unp.h" 2 ssize_t readn(int fd,void *vptr,size_t n) 3 { 4     size_t  nleft; 5     ssize_t nread; 6     char *ptr; 7  8     ptr = vptr; 9     nleft = n;10     while(nleft > 0)11     {12         if((nread = read(fd,ptr,nleft)) < 0 )13         {14             if(errno == EINTR)15             {16                 nread = 0;17             }18             else19             {20                 return -1;21             }22         } 23         else if(nread == 0)24         {25             break;26         }27         nleft -= nread;28         ptr += nread;29     }30     return (n-nleft);31 }
View Code

writen实现代码

 1 #include "unp.h" 2 ssize_t written(int fd,void *vptr,size_t n) 3 { 4     size_t nleft; 5     ssize_t nwritten; 6     const char *ptr; 7     ptr = vptr; 8     nleft = n; 9     while(nlfet >  0)10     {11         if((nwritten = writen(fd,ptr,nleft)) <= 0)12         {13             if(nwritten < 0 && errno ==EINTR)14             {15                 nwritten =0;16             }17             else 18             {19                 return -1;20             }21         }22 23         nleft -= nwritten;24         ptr += nwritten;25     }26     return n; 27 }
View Code

readline实现代码

 1 #include "unp.h" 2 ssize_t readline(int fd, void *vptr, size_t maxlen)  3 {  4      ssize_t n,rc;  5      char    c,*ptr;  6  7      ptr = vptr;  8      for(n = 1; n < maxlen; n++) 9      { 10        if( (rc = read(fd, &c)) == 1)11        { 12          *ptr ++ = c; 13          if(c == '\n') 14            break; 15        }16        else if (r c== 0)17        { 18           *ptr = 0; 19           return (n-1); 20        }else 21           return (-1); 22      } 23 24      *ptr = 0; 25      return (n); 26 } 
View Code

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 肩一边高一边低怎么办 35岁无稳定工作怎么办 机械手表走的快怎么办 机械表发条紧了怎么办 两只乌龟互相咬怎么办? 乌龟鼻子摔烂了怎么办 剃刀龟脖子肿了怎么办 遇见有戾气的人怎么办 身上的寒气太重怎么办 身体里寒气太重怎么办 做人事招不到人怎么办 苹果6cpu坏了怎么办 苹果6s升级不了怎么办 冬天打游戏手冷怎么办 漂流瓶不能用了怎么办 感冒鼻子闻不到味道怎么办 胃难受想吐头晕怎么办 心口窝堵得慌怎么办 嘴巴里苦的很怎么办 怀孕了嘴巴好苦怎么办 嘴巴没味道想吐怎么办 手机流量不够用怎么办移动 sd卡图片不显示怎么办 苹果忘了id账号怎么办 苹果id号忘记了怎么办 7icloud存储满了怎么办 苹果6icloud满了怎么办 电脑内存槽坏了怎么办 苹果7照片删不了怎么办 屋里太冷怎么办小妙招 天气太热,没空调怎么办 8岁儿童发烧39度怎么办 4岁儿童发烧39度怎么办 6岁儿童发烧39度怎么办 手机被晒得很烫怎么办 子宫肌瘤引起的贫血怎么办 月子没做好腰疼怎么办 狗狗屁股流血水怎么办 狗狗屁股在流血怎么办 劳累引起的腰疼怎么办 心口发闷堵的慌怎么办