linux socket 客户端ip,IP地址的三种表示格式及在Socket编程中的应用

使用TCP/IP协议进行网络应用开发的朋友首先要面对的就是对IP地址信息的处理。IP地址其实有三种不同的表示格式:

1)Ascii(网络点分字符串)-

2) 网络地址(32位无符号整形,网络字节序,大头)

3)主机地址 (主机字节序)

IP地址是IP网络中数据传输的依据,它标识了IP网络中的一个连接,一台主机可以有多个IP地址,IP分组中的IP地址在网络传输中将保持不变。下面具体介绍IP地址的三种不同表示格式。

一、点分10进制表示格式

这是我们最常见的表示格式,比如某机的IP地址可能为“202.101.105.66”。事实上,对于Ipv4(IP版本)来说,IP地址是由一个32位的二进制数所构成,但这样一串数字序列无疑是十分冗长并且难以阅读和记忆的。为了方便人们的记忆和使用,就将这串数字序列分成4组,每组8位,并改为用 10进制数进行表示,最后用小原点隔开,于是就演变成了“点分10进制表示格式”。

来看看刚才那个IP地址的具体转化过程:

IP实际地址:11001010011001010110100101000010

分成4组后:11001010   01100101   01101001   01000010

十进制表示:202                  101              105                66

点分表示:202.101.105.66

二、网络字节顺序格式(NBO,Network   Byte   Order)

网络字节顺序格式和主机字节顺序格式一样,都只在进行网络开发中才会遇到。因此,在下面的介绍中,我假设读者对Socket编程知识有一定的基础。

在网络传输中,TCP/IP协议在保存IP地址这个32位二进制数时,协议规定采用在低位存储地址中包含数据的高位字节的存储顺序(大头),这种顺序格式就被称为网络字节顺序格式。在实际网络传输时,数据按照每32位二进制数为一组进行传输,由于存储顺序的影响,实际的字节传输顺序是由高位字节到低位字节的传输顺序。   为了使通信的双方都能够理解数据分组所携带的源地址、目的地址以及分组的长度等二进制信息,无论是主机还是路由器,在发送每一个分组以前,都必须将二进制信息转换为TCP/IP标准的网络字节顺序格式。网络字节顺序格式的地址不受主机、路由器类型的影响,它的表示是唯一的。

3c8ce6380daa33c267ccb0e2e66a02de.png

在Socket编程开发中,通过函数inet_addr和inet_ntoa可以实现点分字符串与网络字节顺序格式IP地址之间的转换。

inet_addr函数原型如下:

unsigned   long   inet_addr(const   char   FAR   *   cp)

函数中的参数cp指向网络中标准的点分地址字符串,其中每个以点分开的数字不可以大于255,这些数字可以是十进制、八进制、十六进制或者混合使用。如 “10.23.2.3”、“012.003.002.024”、“0xa.0x3.0x14.0x2”、“10.003.2.0×12”。

我们在前面的socket编程提到client端的代码,连接本地端口:

/* File Name: client.c */

#include

#include

#include

#include

#include

#include

#include

#define MAXLINE 4096

int main(int argc, char** argv)

{

int    sockfd, n,rec_len;

char    recvline[4096], sendline[4096];

char    buf[MAXLINE];

struct sockaddr_in    servaddr;

if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) 

printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);

exit(0);

}

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(8000);

//可以使用:inet_pton(AF_INET,  "127.0.0.1", servaddr.sin_addr);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//将字符串形式的IP地址转换为按网络字节顺序的整形值

connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) ;

printf("send msg to server: \n");

fgets(sendline, 4096, stdin);

send(sockfd, sendline, strlen(sendline));

irec_len = recv(sockfd, buf, MAXLINE,0);

buf[rec_len]  = '';

printf("Received : %s ",buf);

close(sockfd);

}

三、主机字节顺序格式(HBO,Host   Byte   Order)

主机字节顺序格式顾名思义,其IP地址的格式是和具体主机或者路由器相关的。对于不同的主机,在进行IP地址的存储时有不同的格式,比如对于 Motorola   68k系列主机,其HBO与NBO是相同的。而对于Intel   x86系列,HBO与NBO则正好相反。

在Socket编程中,有四个函数来完成主机字节顺序格式和网络字节顺序格式之间的转换,它们是:htonl、htons、ntohl、和ntohs。 htons和ntohs完成16位无符号数的相互转换,htonl和ntohl完成32位无符号数的相互转换。

在实际应用中我们常见到将端口号转换的例子(如上例)。这是因为,如果用户输入一个数字,而且将指定使用这一数字作为端口号,应用程序则必须在使用它建立地址以前,把它从主机字节顺序转换成网络字节顺序(使用htons()函数),以遵守TCP/IP协议规定的存储标准。相应地,如果应用程序希望显示包含于某一地址中的端口号(例如从getpeername()函数中返回的),这一端口号就必须在被显示前从网络顺序转换到主机顺序(使用ntohs()函数)。

那么,对于IP地址,主机字节顺序格式的转换又有哪些应用呢?

应用一,如果想知道从202.156.2.23到202.156.9.65这两个IP之间到底有多少个主机地址怎么办?这时就可以将两个IP地址转换为主机字节顺序的格式然后相减来得到,具体的实现如下:

int   GetIPCount(char   *   ip1,char   *   ip2)   {

long   pp;;

long   ss;;

pp   =   ntohl(inet_addr(ip1));;

ss   =   ntohl(inet_addr(ip2));;

return(ss   -   pp   +   1);;

}

应用二,如果对一个网段进行扫描,比如,当前正在扫描202.156.23.255,怎么让程序知道下一个应扫的IP是202.156.24.0?这时可以将当前IP转换成主机字节顺序格式并加1后,在转换回网络格式

即可,具体实现如下:

char   *   GetNextIp(char   *   m_curip)   {

struct   sockaddr_in   in;;

long   pp;;

char   *   re;;

pp   =   ntohl(inet_addr(m_curip));;

pp   =   pp   +   1;;

in.sin_addr.s_addr   =   htonl(pp);;

re   =   inet_ntoa(in.sin_addr);;

return   (re);;

}

总结

介绍了IP地址的三种不同表示格式,包括各种格式产生的原因、具体含义以及在Socket编程开发中的一些应用。在实际应用中,必须遵循应用时所应采用的格式标准,同时还应灵活运用格式间的相互转换以及计算技巧。

字节序相关知识

1)字节序

字节序又称端序,尾序,英文:Endianness。在计算机科学领域中,字节序是指存放多字节数据的字节(byte)的顺序,典型的情况是整数在内存中的存放方式和网络传输的传输顺序。Endianness有时候也可以用指位序(bit)。

一般而言,字节序指示了一个UCS-2字符的哪个字节存储在低地址。如果LSByte 在MSByte的前面,即LSB为低地址,则该字节序是小端序;反之则是大端序。在网络编程中,字节序是一个必须被考虑的因素,因为不同的处理器体系可能采用不同的字节序。在多平台的代码编程中,字节序可能会导致难以察觉的bug。

名词:

最低有效位(the least significant bit,lsb):是指一个二进制数字中的第0位(即最低位),具有权值为2^0,可以用它来检测数的奇偶性。与之相反的称之为最高有效位。在大端序中,lsb指最右边的位。

最高有效位(the Most Significant Bit,msb):是指一个n位二进制数字中的n-1位,具有最高的权值

3c8ce6380daa33c267ccb0e2e66a02de.png。与之相反的称之为最低有效位。在大端序中,msb即指最左端的位。

对于有符号二进制数,负数采用反码或补码形式,此时msb用来表示符号,msb为1表示负数,0表示正数。

单字节(abyte):大部分处理器以相同的顺序处理位元(bit),因此单字节的存放方法和传输方式一般相同。

多字节:如整数(32位机中一般占4字节),多字节对象被存储为连续的字节序列,数据的内存地址则是该内存地址的最小地址。

如long型数据的地址是ox001, ox002, ox003,ox004。则该数据的内存地址是ox001。

在不同的处理器的存放多字节数据的方式主要有两种:

大端序(英文名称为big endian):指从最高位起存,位数最大的数字在最前,即高字节存于内存低地址,低字节存于内存高地址, 从最高有效字节到最低有效字节的顺序存储对象。

小端序(英文名称为little endian):指从对低位起存,位数最小的数字在最前。 即低字节存于内存低地址,高字节存于内存高地址,从最低有效字节到最高有效字节的顺序存储对象。

简单打个比方说,十进制数12345。1的位数最高,是万位;5的位数最低,是个位。

大端序的话,就是从万位开始存,表示为12345;

小端序的话,就是从各位开始存,表示为54321.

再如一个long型数据0x12345678的存储表示:

大端序存储表示:

内存地址数据内存低地址–>    a0x00112a+10x00234a+20×00356内存高地址–>a+30×00478

小端序的存储表示:

内存地址数据内存低地址–>a0x00178a+10x00256a+20×00334内存高地址–>a+30×00412

2)网络序

网络传输一般采用大端序,也被称之为网络字节序,或网络序。IP协议中定义大端序为网络字节序。

socketAPI定义了一组转换函数,用于16和32bit整数在网络序和本机字节序之间的转换。htonl,htons用于本机序转换到网络序;ntohl,ntohs用于网络序转换到本机序。

3)位序

一般用于描述串行设备的传输顺序。一般硬件传输采用小端序(先传低位),但I2C协议采用大端序。网络协议中只有数据链路层的底端会涉及到。

4)处理器体系

5) 编程判断大端序和小端序

#include 

bool IsBigEndian(long a)

{

if(((char *)&a)[3] == 1)

return true ;

else

return false ;

}

void main(){

bool b ;

long a = 0x12345678;

b = IsBigEndian(a );

printf("%d", &a);

}

打开VS的内存窗口,查看内存存储方式:

设定断点:

3c8ce6380daa33c267ccb0e2e66a02de.png打开 debug——>window——>Memory

3c8ce6380daa33c267ccb0e2e66a02de.png

查看变量a 的地址:0x002BFE50

3c8ce6380daa33c267ccb0e2e66a02de.png

查看内存地址:

3c8ce6380daa33c267ccb0e2e66a02de.png

从上面看出我使用的x86 ,是小端序。

从而验证 b =false是正确的。

原创文章,作者:s19930811,如若转载,请注明出处:http://www.178linux.com/2988

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输单元(MTU)/路径MTU 以太网帧格式 ICMP ARP RARP 03TCPIP基础(三) IP数据报格式 网际校验和 路由 04TCPIP基础(四) TCP特点 TCP报文格式 连接建立三次握手 连接终止四次握手 TCP如何保证可靠性 05TCPIP基础(五) 滑动窗口协议 UDP特点 UDP报文格式 Linux网络编程之socket编程篇 06socket编程(一) 什么是socket IPv4套接口地址结构 网络字节序 字节序转换函数 地址转换函数 套接字类型 07socket编程(二) TCP客户/服务器模型 回射客户/服务器 socket、bind、listen、accept、connect 08socket编程(三) SO_REUSEADDR 处理多客户连接(process-per-conection) 点对点聊天程序实现 09socket编程(四) 流协议与粘包 粘包产生的原因 粘包处理方案 readn writen 回射客户/服务器 10socket编程(五) read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程与SIGCHLD信号 12socket编程(七) TCP 11种状态 连接建立三次握手、连接终止四次握手 TIME_WAIT与SO_REUSEADDR SIGPIPE 13socket编程(八) 五种I/O模型 select 用select改进回射客户端程序 14socket编程(九) select 读、写、异常事件发生条件 用select改进回射服务器程序。 15socket编程(十) 用select改进第八章点对点聊天程序 16socket编程(十一) 套接字I/O超时设置方法 用select实现超时 read_timeout函数封装 write_timeout函数封装 accept_timeout函数封装 connect_timeout函数封装 17socket编程(十二) select限制 poll 18socket编程(十三) epoll使用 epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 Linux网络编程之进程间通信篇 23进程间通信介绍(一) 进程同步与进程互斥 进程间通信目的 进程间通信发展 进程间通信分类 进程间共享信息的三种方式 IPC对象的持续性 24进程间通信介绍(二) 死锁 信号量 PV原语 用PV原语解决司机与售票员问题 用PV原语解决民航售票问题 用PV原语解决汽车租赁问题 25System V消息队列(一) 消息队列 IPC对象数据结构 消息队列结构 消息队列在内核表示 消息队列函数 26System V消息队列(二) msgsnd函数 msgrcv函数 27System V消息队列(三) 消息队列实现回射客户/服务器 28共享内存介绍 共享内存 共享内存示意图 管道、消息队列与共享内存传递数据对比 mmap函数 munmap函数 msync函数 29System V共享内存 共享内存数据结构 共享内存函数 共享内存示例 30System V信号量(一) 信号量 信号量集结构 信号量集函数 信号量示例 31System V信号量(二) 用信号量实现进程互斥示例 32System V信号量(三) 用信号集解决哲学家就餐问题 33System V共享内存与信号量综合 用信号量解决生产者消费者问题 实现shmfifo 34POSIX消息队列 POSIX消息队列相关函数 POSIX消息队列示例 35POSIX共享内存 POSIX共享内存相关函数 POSIX共享内存示例 Linux网络编程之线程篇 36线程介绍 什么是线程 进程与线程 线程优缺点 线程模型 N:1用户线程模型 1:1核心线程模型 N:M混合线程模型 37POSIX线程(一) POSIX线程库相关函数 用线程实现回射客户/服务器 38POSIX线程(二) 线程属性 线程特定数据 39POSIX信号量与互斥锁 POSIX信号量相关函数 POSIX互斥锁相关函数 生产者消费者问题 自旋锁与读写锁介绍 40POSIX条件变量 条件变量 条件变量函数 条件变量使用规范 使用条件变量解决生产者消费者问题 41一个简单的线程池实现 线程池性能分析 线程池实现
SqlToolBox是一款纯绿色的免费数据库客户端软件,基于Java Swing编制而成,旨在于为开发人员,系统工程师和数据库管理员提供一种通用方便和快捷的数据库操作工具,使他们摆脱需要学习掌握使用多种数据库客户端的苦恼,并减轻他们日常操作数据库和编写Sql语句的任务量,帮助他们把精力投入到解决更有意义的问题上去。 SqlToolBox现有功能 1. 能连接到MySql,Oracle和Ms Sql Server三种数据库。 2. 连接到数据库后,会提供数据库Schema和表的树视图以便用户进行浏览和查找,另外还提供了一个过滤器帮助用户缩小查找范围。 3. 用户能自动快速获取单表的创建,查询,更新,删除,建表语句,整表全部数据插入语句,单表对应Pojo类和单表的Hibernate映射文件等常用文字,且可借此构造更复杂的Sql语句。 4. 能执行Sql语句并显示执行结果,如果是查询语句会以表格形式显示结果,还提供CSV形式数据下载;如果是非查询语句或是错误的查询语句则会以文字形式告知用户。 5. 在用户输入Sql语句的过程提供Sql语法高亮功能,以助于Sql语句的识别。 6. 提供Sql格式化功能以助于Sql语句的识别和整理。 7. 提供Redo/Undo,Shift整体退格进格,大小写转化,将Sql语句用StringBuilder包容以及将Sql语句关键字大写表示等常用文字编辑功能。这些都能帮助程序员在程序书写Sql语句。 8. 能保存和记忆数据库信息,以便下次打开。 。 运行SqlToolBox有何前提条件? 将SqlToolBox运行起来的唯一前提是安装JDK6或以上版本。 SqlToolBox需要安装吗? SqlToolBox是一款纯绿色软件,它对您的系统不做出任何更改,因此不需要安装和卸载。 SqlToolBox安全吗? 由于软件使用Java编写而成,它本身就具有较高的安全性。此外作者保证在SqlToolBox整个系列都不会加入病毒,木马,插件等坏东西。 如何运行SqlToolBox? 解开下载包,然后双击run.bat即可。 在Unix/Linux下如何运行SqlToolBox? 除了也需要安装JDK外,您还需要参照run.bat写一份脚本,然后执行它。 如何使用SqlToolBox打开一个数据库? 程序运行起来后,您将看到一个输入数据库信息的对话框,请依次填入数据库所在机器的IP地址,数据库的库名称,选择数据库的类型以及输入登录数据库的用户名和密码等必要信息。此后再点击“连接数据库”按钮,程序将打开数据库。如果您将以上信息填错也不要紧,程序会提示哪里出现了问题。此外您可以在登录前点击“测试连接”按钮,程序也会告诉您是否能连接到指定的数据库。 打开数据库后程序左边部分如何使用? 成功连接到数据库以后,数据库的Schema和table结构会在画面的左边以树的形式展现出来,如果展现的内容过多,您还可以在上方的“过滤器”输入栏输入关键字以缩小展现范围。在这颗树,表格(table)是以小圆点的方式展现的,左键点击这个圆点,程序将在右侧打开一个Sql语句操作窗口,并执行“select * from table”语句,最后在下方以表格的形式展现给您;如果您用右键点击这个圆点,程序将弹出一个右键菜单,选择其的项目您将可以在右边的Sql语句操作窗口得到单表的字段信息,创建(insert),查询(select),更新(update),删除语句(delete)及建表语句(create table),单表对应Pojo文件,单表的Hibernate映射文件等文字。 打开数据库后程序右边部分是如何使用的? 用左右键点击表格后,您将在右侧看到一个“Sql语句操作窗口”,它分成三部分:工具栏菜单,输入窗口和输出窗口。输入窗口是用以输入,编辑和整理Sql 语句的;工具栏菜单的一大排按钮都是为编辑处理输入窗口的文字而准备的;输出窗口则是展示Sql语句执行后的结果的,如果是查询语句,它会以表格的形式告知您查询的结果,如果是其它语句,它会以文字的形式告知。通常的操作手法是,先在输入窗口用鼠标选您要操作的文本,再在工具栏菜单点击执行特定操作的按钮,然后在下方的输出窗口就能看到具体的结果,当然如果仅是文本编辑操作的话输出窗口是不会有反应的。 如何执行Sql语句? 程序员和数据库管理员总是习惯使用语句来操作数据库,这也是本软件的最重要功能之一。执行Sql语句的过程具体来说是这样做的,首先,在输入窗口输入您向执行的Sql语句,如“select * from table”之类,当然您更可以通过表格的右键菜单来获得常用的sql语句(在输入或是粘贴文本的过程,Sql语句的关键字会以蓝色显示,这是语法高亮功能所致);其次,你需要选你想执行的文本,再点击工具栏菜单的向右三角形按钮,这段文本将得到执行,执行结果将在下方的输出窗口得到展示。如果您执行的是查询语句,输出窗口将以表格的形式列出查询结果集的字段和内容;如果您执行的是删除,更新,添加,修改表等语句或是执行错误的Sql文本,输出窗口将以文本形式告知执行结果。另外工具栏菜单的双向右三角形按钮用于批量执行Sql语句,它以分号“;”来作为每段Sql的分隔标志,然后分别执行每段。 如何快速调整对执行查询语句后得到的表格列宽度? 如果您想自动调整某列的宽度,可以双击这列的表头,此后这列的宽度会根据这列的最长文字进行调整;您还可以在表格上点击右键,选择“调整列宽为最适合状态”一项,那么所有的列宽都会进行调整。 如何得到执行查询语句后得到的表格的内容? 您还可以在表格上点击右键,选择“下载表格为CSV文件”一项,此后查询语句和得到的结果都会被放入一个CSV文件。CSV是一文本文件,但您可以用Excel打开它,也会得到xls文件一样的效果。 在新增或是删除一张表后,在左边的树为什么没有相应的变化? 新增或是删除一张表后,您需要手动执行一下左上方的更新按钮(最上方的大图标第一个),此后程序会重新载入数据库的Schema和table,这样您刚才对表格进行增删操作就能体现出来。 如果我需要常打开数据库进行操作或是需要常操作多个数据库,程序能为我提供那些便利? 本软件有记忆功能,如果您正确连接到一个数据库,那么相应的信息如IP地址,数据库名,数据库类型,连接数据库的用户名和密码都会被记忆下来,这样下次打开时就不用重复输入了。如果您需要常操作多个数据库,您可以通过保存按钮(最上方五个大图标的第二个)将数据库信息保存成XML文件,这样在登录画面就可以通过“打开文件按钮”得到相应的数据库信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值