`
liuguxing
  • 浏览: 92463 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

网络字符顺序与主机字符顺序的区别

阅读更多
存在两种字节顺序:NBO与HBO
网络字节顺序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关

计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换。
  我们要讨论的第一个结构类型是:struct sockaddr,该类型是用来保存socket信息的:
  struct sockaddr {
  unsigned short sa_family; /* 地址族, AF_xxx */
  char sa_data[14]; /* 14 字节的协议地址 */ };
  sa_family一般为AF_INET;sa_data则包含该socket的IP地址和端口号。
  另外还有一种结构类型:
  struct sockaddr_in {
   short int sin_family; /* 地址族 */
   unsigned short int sin_port; /* 端口号 */
   struct in_addr sin_addr; /* IP地址 */
   unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */
  };
  这个结构使用更为方便。sin_zero(它用来将sockaddr_in结构填充到与struct sockaddr同样的长度)应该用bzero()或memset()函数将其置为零。指向sockaddr_in 的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向 sockaddr_in的指针转换为指向sockaddr的指针;或者相反。sin_family通常被赋AF_INET;sin_port和 sin_addr应该转换成为网络字节优先顺序;而sin_addr则不需要转换。
  我们下面讨论几个字节顺序转换函数:
  htons()--"Host to Network Short" ; htonl()--"Host to Network Long"
  ntohs()--"Network to Host Short" ; ntohl()--"Network to Host Long"
  在这里, h表示"host" ,n表示"network",s 表示"short",l表示 "long"。
  打开socket 描述符、建立绑定并建立连接
  socket函数原型为:
  int socket(int domain, int type, int protocol);
  domain参数指定socket的类型:SOCK_STREAM 或SOCK_DGRAM;protocol通常赋值“0”。Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。
  一旦通过socket调用返回一个socket描述符,你应该将该socket与你本机上的一个端口相关联(往往当你在设计服务器端程序时需要调用该函数。随后你就可以在该端口监听服务请求;而客户端一般无须调用该函数)。 Bind函数原型为:
  int bind(int sockfd,struct sockaddr *my_addr, int addrlen);
  Sockfd是一个socket描述符,my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;addrlen常被设置为sizeof(struct sockaddr)。
  最后,对于bind 函数要说明的一点是,你可以用下面的赋值实现自动获得本机IP地址和随机获取一个没有被占用的端口号:
  my_addr.sin_port = 0; /* 系统随机选择一个未被使用的端口号 */
  my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */
  通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将 my_addr.sin_addr.s_addr置为INADDR_ANY,系统会自动填入本机IP地址。Bind()函数在成功被调用时返回0;遇到错 误时返回“-1”并将errno置为相应的错误号。另外要注意的是,当调用函数时,一般不要将端口号置为小于1024的值,因为1~1024是保留端口 号,你可以使用大于1024中任何一个没有被占用的端口号。
  Connect()函数用来与远端服务器建立一个TCP连接,其函数原型为:
  int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
  Sockfd是目的服务器的sockt描述符;serv_addr是包含目的机IP地址和端口号的指针。遇到错误时返回-1,并且errno中包含相 应的错误码。进行客户端程序设计无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户通过哪个端口与服务器建立连接并不需要关心,内 核会自动选择一个未被占用的端口供客户端来使用。
  Listen()——监听是否有服务请求
  在服务器端程序中,当socket与某一端口捆绑以后,就需要监听该端口,以便对到达的服务请求加以处理。
  int listen(int sockfd, int backlog);
  Sockfd是Socket系统调用返回的socket 描述符;backlog指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()它们(参考下文)。Backlog对队列中等待 服务的请求的数目进行了限制,大多数系统缺省值为20。当listen遇到错误时返回-1,errno被置为相应的错误码。
  故服务器端程序通常按下列顺序进行函数调用:
  socket(); bind(); listen(); /* accept() goes here */
  accept()——连接端口的服务请求。
  当某个客户端试图与服务器监听的端口连接时,该连接请求将排队等待服务器accept()它。通过调用accept()函数为其建立一个连 接,accept()函数将返回一个新的socket描述符,来供这个新连接来使用。而服务器可以继续在以前的那个 socket上监听,同时可以在新的socket描述符上进行数据send()(发送)和recv()(接收)操作:
  int accept(int sockfd, void *addr, int *addrlen);
  sockfd是被监听的socket描述符,addr通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息 (某台主机从某个端口发出该请求);addrten通常为一个指向值为sizeof(struct sockaddr_in)的整型指针变量。错误发生时返回一个-1并且设置相应的errno值。
  Send()和recv()——数据传输
  这两个函数是用于面向连接的socket上进行数据传输。
  Send()函数原型为:
  int send(int sockfd, const void *msg, int len, int flags);
  Sockfd是你想用来传输数据的socket描述符,msg是一个指向要发送数据的指针。
  Len是以字节为单位的数据的长度。flags一般情况下置为0(关于该参数的用法可参照man手册)。
  char *msg = "Beej was here!"; int len, bytes_sent; ... ...
  len = strlen(msg); bytes_sent = send(sockfd, msg,len,0); ... ...
  Send()函数返回实际上发送出的字节数,可能会少于你希望发送的数据。所以需要对send()的返回值进行测量。当send()返回值与len不匹配时,应该对这种情况进行处理。
  recv()函数原型为:
  int recv(int sockfd,void *buf,int len,unsigned int flags);
  Sockfd是接受数据的socket描述符;buf 是存放接收数据的缓冲区;len是缓冲的长度。Flags也被置为0。Recv()返回实际上接收的字节数,或当出现错误时,返回-1并置相应的errno值。
  Sendto()和recvfrom()——利用数据报方式进行数据传输
  在无连接的数据报socket方式下,由于本地socket并没有与远端机器建立连接,所以在发送数据时应指明目的地址,sendto()函数原型为:
  int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);
  该函数比send()函数多了两个参数,to表示目地机的IP地址和端口号信息,而tolen常常被赋值为sizeof (struct sockaddr)。Sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。
  Recvfrom()函数原型为:
  int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);
  from是一个struct sockaddr类型的变量,该变量保存源机的IP地址及端口号。fromlen常置为sizeof (struct sockaddr)。当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。Recvfrom()函数返回接收到的字节数或 当出现错误时返回-1,并置相应的errno。
  应注意的一点是,当你对于数据报socket调用了connect()函数时,你也可以利用send()和recv()进行数据传输,但该 socket仍然是数据报socket,并且利用传输层的UDP服务。但在发送或接收数据报时,内核会自动为之加上目地和源地址信息。
  Close()和shutdown()——结束数据传输
  当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:close(sockfd);
  你也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。如你可以关闭某socket的写操作而允许继续在该socket上接受数据,直至读入所有数据。
  int shutdown(int sockfd,int how);
  Sockfd的含义是显而易见的,而参数 how可以设为下列值:
  ·0-------不允许继续接收数据
  ·1-------不允许继续发送数据
  ·2-------不允许继续发送和接收数据,均为允许则调用close ()
  shutdown在操作成功时返回0,在出现错误时返回-1(并置相应errno)。
  DNS——域名服务相关函数
  由于IP地址难以记忆和读写,所以为了读写记忆方便,人们常常用域名来表示主机,这就需要进行域名和IP地址的转换。函数gethostbyname()就是完成这种转换的,函数原型为:
  struct hostent *gethostbyname(const char *name);
  函数返回一种名为hosten的结构类型,它的定义如下:
  struct hostent {
   char *h_name; /* 主机的官方域名 */
   char **h_aliases; /* 一个以NULL结尾的主机别名数组 */
   int h_addrtype; /* 返回的地址类型,在Internet环境下为AF-INET */
   int h_length; /*地址的字节长度 */
   char **h_addr_list; /* 一个以0结尾的数组,包含该主机的所有地址*/
  };
 #define h_addr h_addr_list[0] /*在h-addr-list中的第一个地址*/
2、将主机的unsigned long值转换为网络字节顺序(32位):为什么要这样做呢?因为不同的计算机使用不同的字节顺序存储数据。因此任何从Winsock函数对IP地址和端口号的引用和传给Winsock函数的IP地址和端口号均时按照网络顺序组织的。
      u_long htonl(u_long hostlong);
      举例:htonl(0)=0
      htonl(80)= 1342177280
3、将unsigned long数从网络字节顺序转换位主机字节顺序,是上面函数的逆函数。       u_long ntohl(u_long netlong);
      举例:ntohl(0)=0
      ntohl(1342177280)= 80
4、将主机的unsigned short值转换为网络字节顺序(16位):原因同2:       u_short htons(u_short hostshort);
      举例:htonl(0)=0
      htonl(80)= 20480
5、将unsigned short数从网络字节顺序转换位主机字节顺序,是上面函数的逆函数。       u_short ntohs(u_short netshort);
      举例:ntohs(0)=0
      ntohsl(20480)= 80
分享到:
评论

相关推荐

    计算机网络复习题

    6.简述IP地址与硬件地址的区别。 IP地址是网络层和以上各层使用的地址(1分),是一种逻辑地址,IPv4地址32位(4字节)(1分),IPv6地址128位(16字节)(1分) MAC地址是数据链路层的和物理层使用的地址(1分),...

    JAVA局域网飞鸽传书软件设计与实现

    inet_ntoa函数将一个网络字节顺序的32位IP地址转化字符串。注意:inet_addr返回的32位二进制数是用网络顺序存储的。 根据用户需求,本系统分为两个子系统:1:局域网内简单文字聊天子系统,它是在局域网内选择相应...

    全国计算机等级考试系列 (二级)-C 语言题库

    【试题答案与讲析】 基础知识 1.B。计算机主机不能缺少的是CPU和内存,这也是主机主要包括的部件。 2.D。存取速度的比较顺序为内存>硬盘>软盘>光盘。 3.A。操作系统可以说是计算机的灵魂,没有了操作系统...

    网络工程师考点汇总

    2、帧中继与X.25的差别:(1)呼叫控制信号与用户数据采用分开的逻辑连接,这样,中间结点就不必维护与呼叫控制有关的状态表或处理信息;(2)在第二层而不是在第三层实现逻辑连接的多路复用和交换,这样就省掉了整个一...

    VBScript 语言参考中文手册CHM

    StrReverse 函数 返回一字符串,其中字符的顺序与指定的字符串中的顺序相反。 Sub 语句 声明形成 Sub 过程体的名称、参数和代码。 减法运算符 (-) 求两数之差,或表示某数值表达式的相反数。 语法错误 VBScript ...

    VBScript 语言参考

    StrReverse 函数 返回一字符串,其中字符的顺序与指定的字符串中的顺序相反。 Sub 语句 声明形成 Sub 过程体的名称、参数和代码。 减法运算符 (-) 求两数之差,或表示某数值表达式的相反数。 语法错误 VBScript ...

    VBSCRIP5 -ASP用法详解

    StrReverse 函数 返回一字符串,其中字符的顺序与指定的字符串中的顺序相反。 Sub 语句 声明形成 Sub 过程体的名称、参数和代码。 减法运算符 (-) 求两数之差,或表示某数值表达式的相反数。 语法错误 VBScript ...

    《计算机应用基础》在线考核.doc

    福建师范大学网络与继续教育学院 《计算机应用基础》期末考试A卷 姓名: 专业: 学号: 学习中心: 缺考标记,考生禁填! 答案务必写在答题纸上,否则不得分! 1. 单项选择题(每小题1分,共40分,请在答题纸上填写...

    网络基础知识.DOC

    一、OSI七层协议 OSI(Open System ... 还包括加密与解密、压缩与解压缩等。 7、应用层 应用层应该是直接面向用户的程序或服务,包括系统程序和用户程序, 例如www、FTP、DNS、POP3和SMTP等都是应用层服务。

    javascript文档

    getTimezoneOffset 方法 返回主机的时间和全球标准时间(UTC)之间的差(以分钟为单位)。 getUTCDate 方法 使用全球标准时间(UTC)返回 Date 对象的日期值。 getUTCDay 方法 使用全球标准时间(UTC)返回 Date ...

    JScript 语言参考

    getTimezoneOffset 方法 返回主机的时间和全球标准时间(UTC)之间的差(以分钟为单位)。 getUTCDate 方法 使用全球标准时间(UTC)返回 Date 对象的日期值。 getUTCDay 方法 使用全球标准时间(UTC)返回 Date ...

    微软JavaScript手册

    getTimezoneOffset 方法 返回主机的时间和全球标准时间(UTC)之间的差(以分钟为单位)。 getUTCDate 方法 使用全球标准时间(UTC)返回 Date 对象的日期值。 getUTCDay 方法 使用全球标准时间(UTC)返回 Date ...

    win7 超级终端

    迄今为止,计算技术经历了主机时代、PC时代和网络计算时代这三个发展时期,终端与计算技术发展的三个阶段相适应,应用也经历了字符哑终端、图形终端和网络终端这三个形态。 三、命令行接口 命令行是GRUB最基本的...

    入门学习Linux常用必会60个命令实例详解doc/txt

    -i: 在重开机之前先把所有与网络相关的装置停止。 install 1.作用 install命令的作用是安装或升级软件或备份数据,它的使用权限是所有用户。 2.格式 (1)install [选项]... 来源 目的地 (2)install [选项]... ...

    计算机网络技术20秋在线作业1-0001.docx

    ( ) A:错误 B:正确 答案:B 点一点式网络与广播式网络在技术上有重要区别。点一点式网络需要采用分组存储转发与路由选择。() A:错误 B:正确 答案:B IP 分组格式中,数据报头部长度的最小值为20个字节,最大值为...

    计算机等级考试试题系统

    为了能在网络上正确地传送信息,制定了一整套关于传输顺序,格式,内容和方 式的约定,称之为( ) A. OSI参考模型 B.网络操作系统 C.通信协议 D.网络通信软件 3.衡量网络上数据传输速率的单位是每秒传送多少个二...

    计算机网络常见问题解答

    问题1-14:网络的吞吐量与网络的时延有何关系? 问题1-15:什么是“无缝的”、“透明的”和“虚拟的”? 问题1-16:在教材的1.7.2节提到协议有三个要素,即语法、语义和同步。语义是否已经包括了同步的意思? 问题1-...

    台达DVP-PM 应用技术手册【程式篇】.pdf

    ASCII / RTU通讯协议,数据存储器:10,000字符(停电保持),500kHz高速脉冲输出,可实现3轴螺旋插补、3轴直线插补、任2轴直线、圆弧插补等功能,支持手摇轮(MPG)与多点外部讯号输入,支持电子凸轮功能、飞剪、追剪...

    hiera-regex:Hiera Regex将客户事实与正则表达式字符串进行匹配以提供分层数据

    Hiera正则表达式是Hiera的数据后端,可将客户事实与正则表达式字符串进行匹配。 一个典型的用例是与主机名模式匹配,而不是使用每个FQDN都需要自己的文件的标准文件后端。 这个怎么运作 除用于查找数据的文件名外,...

    20秋学期(1909、2003、2009-)《计算机网络管理》在线作业-(1).docx

    D:队列调度器(scheduler) 答案:A MRTG软件的功能是() A:扫描系统漏洞 B:构建防火墙 C:监测网络流量 D:测试Web服务器访问压力 答案:C OSI严格遵循网络分层模式,提供了很好的参考标准,分层的顺序为() ...

Global site tag (gtag.js) - Google Analytics