今天我们说说“Pre-网络编程”。内容比较杂,但都是在做网络应用程序开发过程中经常要遇到的问题。

  一、大端、小端和网络字节序

  小端字节序:little-endian,将低字节存放在内存的起始地址;

  大端字节序:big-endian,将高字节存放在内存的其实地址。

例如,数字index=0x11223344,在大小端字节序方式下其存储形式为:

  上图一目了然的可以看出大小端字节序的区别。

  还有另外一个概念就是网络字节序。网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian方式。注意:X86系列CPU都是小端little-endian字节序,即低字节存低位,高字节存高位。

  为此,Linux专门提供了字节转换函数.

unsigned long  int htonl(unsigned long  int hostlong)

unsigned short int htons(unisgned short int hostshort)

unsigned long  int ntohl(unsigned long  int netlong)

unsigned short int ntohs(unsigned short int netshort)

看个例子:

  在这四个转换函数中,h代表host,n代表 network,s代表short,l代表long 。htonl()函数的意义是将本机器上的long数据转化为网络上的long。其他几个函数的意义也差不多。

也就是说对于从网络上接收到的非单子节的基本数据类型数据,首先需要用ntohl(s)将其转换成本地字节序;同理,发往网络的非单子节的基本数据类型数据,首先用htonl(s)将其转换成网络字节序。这里最常见的就是IP地址和端口号。

  二、点分十进制格式的IP地址和32bit的IP地址

我们常见的IP地址都是以点分十进制格式表示,例如“172.18.1.231”。而在程序中基本是以如下的结构表示一个IP:

struct in_addr {
__be32 s_addr; //其实就是一个32bit的数字 };

它和点分十进制格式的IP地址可以通过一组API实现相互转换:

int inet_aton(const char *cp,struct in_addr *inp) 无效的地址cp则返回0;否则返回非0

char *inet_ntoa(struct in_addr in) 将一个32位的IP地址转换成点分十进制字符串。

这两个函数所要求的struct in_addr{}参数均为网络字节序。

继续看例子:

 
 

“192.168.11.23”转换成数字就是0xc0a80b17,是网络字节序的。如果直接打印,那么本地按照小端字节序来输出,结果为net addr = 170ba8c0,刚好和实际相反。当我们先将其转换成本地字节序,然后再输出时结果就OK了,即host addr = c0a80b17。同理,inet_ntoa()也类似。

  三、网络主机名和IP地址的对应关系

在做网络编程时经常要碰到的一个问题就是根据对方主机名来获取其IP地址,或者根据IP地址反过来解析主机名和其他信息。Linux提供了两个常用的API:

struct hostent *gethostbyname(const char *name);

struct hostent *gethostbyaddr(const void *addr, int len, int type);

这两个函数失败时返回NULL且设置h_errno错误变量,调用hstrerror(h_errno)或者herror("Error");可以得到详细的出错信息。成功时均返回如下结构:

struct hostent {

     char    *h_name;        /* 主机名*/

     char    **h_aliases;    /* 主机别名的列表*/

     int     h_addrtype;     /* 地址类型,AF_INET或其他*/

     int     h_length;       /* 所占的字节数,IPv4地址都是4字节 */

     char    **h_addr_list;  /* IP地址列表,网络字节序*/

}

#define h_addr  h_addr_list[0]  /*后向兼容 */

gethostbyname可以将机器名(如www.google.com)转换为一个结构指针,gethostbyaddr可以将一个32位的IP地址(C0A80001)转换为结构指针。对于gethostbyaddr函数来说,输入参数“addr”的类型根据参数“type”来确定,目前type仅取AF_INET或AF_INET6。例如,type=2(即AF_INET),则addr就必须为struct in_addr{}类型。

继续看例子:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h> int main(int arg,char** argv){ struct hostent *host,*host2; if(NULL == (host = gethostbyname(argv[]))){ herror("Error"); return ; } printf("name = %s\n",host->h_name); printf("aliases = %s\n",*host->h_aliases); printf("add type = %d\n",host->h_addrtype); printf("len = %d\n",host->h_length); printf("IP=%s\n",inet_ntoa(*(struct in_addr*)host->h_addr)); printf("=================================\n"); struct in_addr maddr; if( == inet_aton(argv[],&maddr)){ return ; } char* c = (char*)&maddr; printf("org = %x.%x.%x.%x\n",*(c)&0xff,*(c+)&0xff,*(c+)&0xff,*(c+)&0xff); if(NULL == (host2 = gethostbyaddr(&maddr,,))){ printf("Error:%s\n",hstrerror(h_errno)); return ; } printf("name = %s\n",host2->h_name); printf("aliases = %s\n",*host2->h_aliases); printf("add type = %d\n",host2->h_addrtype); printf("len = %d\n",host2->h_length); printf("IP=%s\n",inet_ntoa(*(struct in_addr*)host2->h_addr)); return ; }

运行结果如下:

       当我们调用gethostbyaddr根据主页的IP地址获取其站点信息时返回的错误是“未知的主机”错误,原因留给大家自己思考吧。这充分说明对了于gethostbyname()函数和gethostbyaddr()函数的调用一定要判断其返回值。

Linux环境下网络编程杂谈《转》的更多相关文章

  1. Linux 环境下 网络IO模型

    本文讨论的背景是Linux环境下的network IO. IO发生时涉及的对象和步骤: 对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的proce ...

  2. 【原创】Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

    Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区 ...

  3. Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

    转:https://www.cnblogs.com/shoemaker/p/linux_graphics01.html Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过 ...

  4. 在linux环境下python与C++混合编程

    参考:在linux环境下编译C++ 程序 linux下python3调用c代码或者python3调用c++代码 https://blog.csdn.net/u013179327/article/det ...

  5. linux环境下学习使用pro*c/c++工具

    1.proc是oracle用来预编译嵌入SQL语句的c程序. 2.如何使用proc工具 在Linux环境下,首先确保gcc编译器正常使用,安装oracle数据库或者客户端,一般就会默认安装pro*c/ ...

  6. java 在linux环境下写入 syslog 问题研究

    1.Syslog 在Unix类操作系统上,syslog广泛应用于系统日志.syslog日志消息既可以记录在本地文件中,也可以通过网络发送到接收syslog的服务器.接收syslog的服务器可以对多个设 ...

  7. 关于ARP攻击的原理以及在Kali Linux环境下的实现

    关于ARP攻击的原理以及在Kali Linux环境下的实现 全文摘要 本文讲述内容分为两部分,前半部分讲述ARP协议及ARP攻击原理,后半部分讲述在Kali Linux环境下如何实现ARP攻击以及AR ...

  8. linux环境下安装sphinx中文支持分词搜索(coreseek+mmseg)

     linux环境下安装sphinx中文支持分词搜索(coreseek+mmseg) 2013-11-10 16:51:14 分类: 系统运维 为什么要写这篇文章? 答:通过常规的三大步(./confi ...

  9. 多线程编程之Linux环境下的多线程(三)

    前面两篇文章都讲述了Linux环境下的多线程编程基础知识,也附带了典型实例.本文主要比较一下Linux环境与Windows环境下的多线程编程区别. 看待技术问题要瞄准其本质,不管是WIN32.Linu ...

随机推荐

  1. Revit MEP API找到连接器连接的连接器

    通过conn.AllRefs;可以找到与之连接的连接器. //连接器连接的连接器 [TransactionAttribute(Autodesk.Revit.Attributes.Transaction ...

  2. Promise,Generator(生成器),async(异步)函数

    Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...

  3. Task Parallel Library01,基本用法

    我们知道,每个应用程序就是一个进程,一个进程有多个线程.Task Parallel Library为我们的异步编程.多线程编程提供了强有力的支持,它允许一个主线程运行的同时,另外的一些线程或Task也 ...

  4. lufylegend:图形变形3

    面来看看drawtriangles函数的扩展.利用drawtriangles函数来实现一个旋转的3D地球,效果如下 因为lufylegend1.5.0版的drawtriangles函数有个bug,所以 ...

  5. tms web core介绍

    tms web core介绍 TMS Web CORE是基于将Delphi UI代码编译为javascript并以此方式创建的 称为单页应用程序.TMS Web核心应用程序可以包含多个表单. 这些多个 ...

  6. 【CentOS】centos7上查看服务开机启动列表

    centos7上查看服务开机启动列表 命令: systemctl list-unit-files; 点击回车,可以向下翻页查询

  7. Android之一种很有趣的界面跳动提示动画

    上一个效果图: ==================================== 先上布局: <RelativeLayout xmlns:android="http://sch ...

  8. Logstash使用jdbc_input同步Mysql数据时遇到的空时间SQLException问题

    今天在使用Logstash的jdbc_input插件同步Mysql数据时,本来应该能搜索出10条数据,结果在Elasticsearch中只看到了4条,终端中只给出了如下信息 [2017-08-25T1 ...

  9. sulime代理设置、插件管理

    使用command palette或者package control,可以管理插件:安装.更新.启动.关闭插件.卸载插件等 配置Package Control 配置举例: { "bootst ...

  10. jvm垃圾回收原理(转)

    原文链接:jvm垃圾回收原理 在jvm中堆空间划分为三个代:年轻代(Young Generation).年老代(Old Generation)和永久代(Permanent Generation).年轻 ...