Linux环境下网络编程杂谈《转》
今天我们说说“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 ; }
运行结果如下:

Linux环境下网络编程杂谈《转》的更多相关文章
- Linux 环境下 网络IO模型
本文讨论的背景是Linux环境下的network IO. IO发生时涉及的对象和步骤: 对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的proce ...
- 【原创】Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介
Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区 ...
- Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介
转:https://www.cnblogs.com/shoemaker/p/linux_graphics01.html Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过 ...
- 在linux环境下python与C++混合编程
参考:在linux环境下编译C++ 程序 linux下python3调用c代码或者python3调用c++代码 https://blog.csdn.net/u013179327/article/det ...
- linux环境下学习使用pro*c/c++工具
1.proc是oracle用来预编译嵌入SQL语句的c程序. 2.如何使用proc工具 在Linux环境下,首先确保gcc编译器正常使用,安装oracle数据库或者客户端,一般就会默认安装pro*c/ ...
- java 在linux环境下写入 syslog 问题研究
1.Syslog 在Unix类操作系统上,syslog广泛应用于系统日志.syslog日志消息既可以记录在本地文件中,也可以通过网络发送到接收syslog的服务器.接收syslog的服务器可以对多个设 ...
- 关于ARP攻击的原理以及在Kali Linux环境下的实现
关于ARP攻击的原理以及在Kali Linux环境下的实现 全文摘要 本文讲述内容分为两部分,前半部分讲述ARP协议及ARP攻击原理,后半部分讲述在Kali Linux环境下如何实现ARP攻击以及AR ...
- linux环境下安装sphinx中文支持分词搜索(coreseek+mmseg)
linux环境下安装sphinx中文支持分词搜索(coreseek+mmseg) 2013-11-10 16:51:14 分类: 系统运维 为什么要写这篇文章? 答:通过常规的三大步(./confi ...
- 多线程编程之Linux环境下的多线程(三)
前面两篇文章都讲述了Linux环境下的多线程编程基础知识,也附带了典型实例.本文主要比较一下Linux环境与Windows环境下的多线程编程区别. 看待技术问题要瞄准其本质,不管是WIN32.Linu ...
随机推荐
- C#写UTF8文件时指定是否含BOM头
BOM的基本概念 在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF.而FFFE在UCS中是不存在的字符,所以不应该出现在实 ...
- Android 性能优化的一些方法
1.采用硬件加速,在androidmanifest.xml中application添加 android:hardwareAccelerated="true".不过这个需要在and ...
- ibatis.net:在VS中支持xml智能提示
下载ibatis.net,在其解压目录下有几个后缀为“.xsd”的文件,将他们拷贝到如下目录:
- 一分钟了解ArrayList和Vector的区别
一.是否是线程安全的 Vector是同步的, 而ArrayList不是.因为Vector是同步的, 所以它是线程安全的.同样, 因为Vecotr是同步的, 所以他需要额外的开销来维持同步锁, 所以它要 ...
- 安卓开发环境配置及HelloWorld
一:JAVA 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 1.1 ...
- C# 异步编程Task整理(二)异常捕捉
一.在任务并行库中,如果对任务运行Wait.WaitAny.WaitAll等方法,或者求Result属性,都能捕获到AggregateException异常. 可以将AggregateExceptio ...
- MAPI错误0x80040107
MAPI错误0x80040107 的解决方案: The MAPI error means there's an "invalid entry" within the contac ...
- @Autowired注解和静态方法 NoClassDefFoundError could not initialize class 静态类
NoClassDefFoundError could not initialize class 静态类 spring boot 静态类 java.lang.ExceptionInInitializer ...
- [leetcode]Subsets II @ Python
原题地址:https://oj.leetcode.com/problems/subsets-ii/ 题意: Given a collection of integers that might cont ...
- 读书笔记,《深入理解java虚拟机》,第二章,java内存区域与内存溢出异常
第二节,运行时数据区域. 在这个章节中,作者给出了一个java虚拟机运行时数据区的框图,图的左侧是方法区和堆,这两个数据区是所有的线程所共享的.然后是虚拟机栈.本地方法栈.还有程序计数器,这三个 ...