什么是字节序(端序、低端字节序、高端字节序、网络字节序)

前言

一个内容为12(字符串)的文本文件,它的第一个字节是什么(小端序)?如果你的回答是0x32,那你真的应该好好理解下字节序了。如下图所示,我这里的正确答案是0x31。当然如果你的回答是不一定,这似乎也是对的。背后的原因比较复杂。
在这里插入图片描述

什么是字节序

首先,字节序又称端序,顾名思义“字节的顺序”。你可能会奇怪:字节还有顺序?让我们从生活中常见概念入手吧。

生活中的数

123456,如果让你把这串数读出来的话你肯定会说:“十二万三千四百五十六。”你瞧,从左往右,这就是我们读数字时的顺序。
那有没有从右往左看数字的时候呢?当然有!如果我让你计算123456+134659你肯定会先从个位算起(除非你想给自己找麻烦)。

把数存入内存

计算机不是神仙,它和你没有心灵感应。因此为了使CPU可以读取数据,我们要先把数据存入内存再让CPU读取。内存是按地址进行访问的存储器件。在内存中,每个字节都有它对应的地址。
那么,你要如何把数0x12345678存入内存呢?
在这里插入图片描述
一种存储方式如下所示。
在这里插入图片描述
当然你也可以选择另外一种存储方式。
在这里插入图片描述
以上两种方式没有对错之分,只要在存储和读取时保持一致即可。Intel公司的CPU普遍采用第二种方式。

字节序的小端序与大端序

  • 像Intel这样把数的低字节存在内存低地址处的方案,我们称作小端序(Little-Endian),全称字节序的小端序,又称低(小)端字节序等。
  • 反之,像第一种把数的高字节存在内存低地址处的方案,我们称作大端序(Big-Endian),全称字节序的大端序,又称高(大)端字节序等。

端序

你肯定要迫不及待地问,前文一直在说的究竟是什么呢?顾名思义,端(end)就是一边、一头、一端的意思:

  • 内存中,我们以低地址为端
  • 网络传输中,我们以0时刻发送的数据为

因此字节序的大端序更精确的定义为:位置更高(重要,significant)的字节在端;相反,字节的小端序更精确的定义为位置更低(不重要)的字节在端
大端序和小端序是两种不同的端序。现在Intel公司的CPU普遍采用字节小端序(字节序的小端序)。
因此下图以字节小端序读取的结果是0x78563412,以字节大端序读取的结果是0x12345678.
在这里插入图片描述

注意: 当数据按上图在内存中存储时,不存在(至少据我所知,不存在) 0x87654321或者0x21345678这样的读取顺序.这是因为内存是以字节为最小单位进行存取的,所以字节内比特(位)的顺序总是固定不变的。当数据在网络中传输时就会涉及到字节内位的顺序

数据在网络中传输

网络字节序

根据RFC791,网络传输时(精确地说是使用IP协议进行网络传输时)以太网采用大端字节序,即先发送位置更高(重要,significant)的字节。对于0x78563412来说0x78位置更高,因此应先发送0x78。
但是由此引发了一个问题,不管CPU是大端还是小端,根据RFC791 Figure 10,只要低地址0x34存着数据0x12,就应当先发送数据0x12(实际上,网卡发送数据时也都是从低字节处开始发送,不论端序如何)。而当在小端系统中存储0x78563412时,其在内存中的表示如下图所示。按照RFC791,将发送0x12,但是按照大端序,却应对先发送0x78. 因此C语言提供了htonl和ntohl这两个函数来帮我们解决主机字节序与网络字节序之间的转换问题。在发送数据前和接收数据后先通过这两个函数对字节序进行转换。
在这里插入图片描述

网络比特序

以太网是串行传输数据的,即一次只能发送一个比特位。这样就引出了一个问题:我们知道,要想传输0x1234,需要先发送0x12这个字节,可是对于0x12我们应该先发送哪一位呢?
0x12的二进制写法是00010010B,因此有两种发送顺序。即,按照时间顺序依次发送0-0-0-1-0-0-1-0,或者反过来,发送0-1-0-0-1-0-0-0. 网络以0时刻为端,在发送0-0-0-1-0-0-1-0时比特的高位(重要的那一位)在端,我们称之为大端比特序;反之发送0-1-0-0-1-0-0-0时比特的低位(不那么重要的位)在端,我们称之为小端比特序。那么网络比特序是大端序还是小端序呢?

至于以太网在硬件层面是否真的是严格串行传输的,我并不清楚。因为ISO/IEC/IEEE 8802-3:2021居然有5千多页,鄙人才疏学浅,找不出来。

在这里插入图片描述
在这里插入图片描述
在RFC791和Linux内核中对于IP头部的定义如上图所示。可以发现,Linux为大端序和小端序提供的不同的定义。对于C的位域来说,先定义的成员位于低比特为,即0bit。对于小端系统,bit0至bit3为ihl,bit4至bit7为version。对于大端系统则反过来。根据RFC791要求,应当先发送version字段。对于网卡来说,先发送比特的高位(重要的那一位),再发送比特的低位(不重要的那一位);网卡在接收bit数据的时候,同样认为先收到MSB(Most Significant Bit),最后收到的位LSB(Least Significant Bit). 在小端系统中,MSB为bit7, LSB为bit0;在大端系统中,MSB为bit0, LSB为bit7.
综上所述,网卡会自动帮我们处理网络传输中的比特序问题。数据存取的最小单位通常是字节,而非比特,因此在一般的编程中,我们不必纠结于比特序的问题。

参考 https://blog.csdn.net/shaohui973/article/details/115766497

考考你

为了确保你真的懂了,现在考虑一个问题。假设有多字节数0x55AA需要发送,那么应该先发送哪一位或者哪一比特呢?

从字节序的角度

以太网是字节序的大端序,因此对于0x55AA,先发送MSB,即0x55. 在小端系统中,0x55位于高字节,需经过htonl转换后再发送。

从比特序的角度

首先明确肯定会先发送0x55这个字节(高端字节序)。0x55=01010101B. MSB为0,因此发送顺序为0-1-0-1-0-1-0-1. 在大端系统中,0位于bit0,1位于bit7;在小端系统中,1位于bit0,0位于bit7. 无论大端小端,网卡都会先发送MSB。

开头的问题

在这里插入图片描述
严格地说,文件中没有“大小端序”这个概念,不然,文件在不同端序CPU的系统上将无法通用,这肯定是我们不希望看到的。
在C#中,文件是按字节写入,因此不存在端序的问题——你想写什么就写什么。
在这里插入图片描述
在test1文件中,由于使用的是小端序CPU,变量的第一个字节自然是0x78,第二个字节是0x56……C#会直接把这个数组原封不动地写入文件。至于test2,字符1的utf-8编码是0x31,2是0x32……C#也会将他们原样写入文件。很多高级语言都是这样。
在这里插入图片描述
需要特别注意:在计算机中,字节序的概念被限制在CPU中,对于字节序的讨论应该和CPU息息相关。例如,汇编语言、操作系统等。 同理,关于比特序的讨论应该被限制在需要它的地方——网络的物理层/数据链路层的底部。像内存、硬盘这些设备只要符合规范,就可以在任何端序的CPU中使用。换句话说,它们本身都没有字节序的概念。
所以如果你拿着wireshark的截图问我:为啥在小端的CPU中出现了大端序,这个……我只能说它编程时就是这么设计的。毕竟这样你用起来更舒服。
在这里插入图片描述

后记

CPU是个傻瓜,它并不清楚你的意图,只是按照你的指示做事。你要做什么,你自己是最清楚的。
好比我问你10100001B到底是有符号数还是无符号数,答案是:它既是无符号数161也是有符号数-95. 至于怎么解释完全取决于你自己。
书是从左往右读的,但古代的书都是从右往左读。这并不会影响书籍的内容,只要写和读的时候顺序一致即可。

  • 14
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Java经典入门教程pdf完整版Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 3;Java是一种软件运行平台 3.1:什么是软件的运行平台 如同我们需要阳光、空气、水和食物才能正常存活一样,软件最终要能够运行,也需要 系列旳外部环境,来为软件的运行提供支持,而提供这些支持的就是运行平台。 3.2:Java是一种运行平台 Java本身提供Java软件所需要的运行环境,Java应用可运行在安装了JRE(Java Runtime environment)的机器上,所以我们说Java是一个运行平台。 JRE: Java Runtime Environment,Java运行环境。 4:Java是一种软件部署环境 4.1:什么是软件的部署 简单地讲,部署就是安装,就是把软件放置到相应的地方,并且进行相应的配置(一般 称作部署描述),让软件能够正常运行起来。 4.2:Java是一种软件部署环境 ava本身是一个开发的平台,开发后的Java程序也是运行在Java平台上的。也就是说, 开发后的Java程序也是部署在Java平台上的,这个尤其在后面学习JEE(Java的企业版) 的时候,体现更为明显 :Java能干什么 JaⅦa能做的事情很多,涉及到编程领域的各个方面。 1:桌面级应用:尤其是需要跨平台的桌面级应用程序。 先解释一下桌面级应用:简单的说就是主要功能都在我们本机上运行的程序,比如 word、 excel等运行在木机上的应用就属」桌面应用。 2:企业级应用 先解释一下企业级应用:简单的说是大规模的应用,一般使用人数较多,数据量较大, 对系统的稳定性、安全性、可扩展性和可装配性等都有比较高的要求 这是目前Java应用最广泛的一个领域,几乎一枝独秀。包括各种行业应用,企业信息、 化,也包括电子政务等,领域涉及:办公自动化OA,客户关系管理CRM,人力资源HR, 企业资源计划ERP、知识管理KM、供应链管理SCM、企业设备管理系统EAM、产品生命 周期管理PLM、面向服务体系架构SOA、商业智能BⅠ、项日管理PM、营销管理、流程管 理 Work Flow、财务管理…..等几乎所有你能想到的应用 3:嵌入式设备及消费类电子产品 包括无线手持设备、智能卡、通信终端、医疗设备、信息家电(如数字电视、机顶盒 电冰箱)、汽车电子没备等都是近年以来热门的Java应用领域,尤其是手机上的Java应用 程序和Java游戏,更是普及。 4:除了上面提到的,Java还有很多功能:如进行数学运算、显示图形界面、进行网络操作、 进行数据库操作、进行文件的操作等等。 PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 三:Java有什么 Java体系比较庞杂,功能繁多,这也导致很多人在自学Java的时候总是感觉无法建立 全面的知识体系,无法从整体上把握Java的原因。在这里我们先简单了解一下Java的版本 具体的Java体系知识结构,将在后面详细讲述。 Java分成三种版本,分别是Java标准版(JSE)、Java微缩版JME)和Java企业版(JE), 每一和版本都有自己的功能和应用方向。 1:Java标准版:JSE( Java standard Edition) JSE( Java Standard edition)是sun公司针对桌面开发以及低端商务计算解决方案而开 发的版本,例如:我们平常熟悉的 Application桌面应用程序。这个版本是个基础,它也是 我们半常开发和使用最多的技术,Java的主要的技术将在这个版本中体现。本书主要讲的 就是JSF。 2:Java微缩版:JME( Java Micro edition) JE(Java, Micro edition)是对标准版JSE进行功能缩减后的版本,于199年6月 由 Sun Microsystems第一次推向Java团体。它是一项能更好满足Java开发人员不同需求 的广泛倡议的一部分。 Sun Microsystems将JM定义为“一种以广泛的消费性产品为目标 的高度优化的Java运行时环境,包括寻呼机、移动电话、可视电话、数字机顶盒和汽车导 航系统。” JE是致丿于消费产品和嵌入式设备的开发人员的最佳选择。尽管早期人们对它看好而 且Java开发人员团体中的热衷人土也不少,然而,J最近才开始从其影响更大的同属 品JEE和JSE的阴影中走出其不成熟期。 JME在开发面向內存有限的移动终端(例如寻呼机、移动电话)的应用时,显得尤其实用。 因为它是建立在操作系统之上的,使得应用的丌发无须考虑太多特殊的硬件配置类型或操作 系统。因此,开发商也无须为不同的终端建立特殊的应用,制造商也只需要简单地使它们的 操作平台可以攴持JM便可, 3:Java企业版:JEE( Java enterprise edition) JE( ava Enterprise edition)是·种利用Java平台来简化企业解决方案的开发、部 著和管理相关的复杂问题的体系结构。JE技术的基础就是核心Java平台或Java平台的标 准版,JEE不仅巩固了标淮版屮的诈多优点,例如“编写一次、随处运行”的特性、方便存 取数据库的 JDBC API、 CORBA技术以及能够在 Internet应用中保护数据的安全模式等等, 同时还提供了对BJB( Enterprise java beans)、 Java Servlets aPi、JSP( Java Server pages) 以及ⅫML技术的全面攴持。其最终目的就是成为一个能够使企业开发者大幅缩短投放市场时 间的体系结构。 JEE体系结构提供屮间层集成框架来满足无需太多费用而又需要高可用性、高可靠性以 及可扩展性的应用的需求。通过提供统的开发平台,J降低了开发多层应用的费用和复 杂性,同时提供对现有应用稈序集成强有力支持,完全支持 Entcrprise java beans,有良 好的向导攴持打包和部署应用,添加了目录攴持,增强了安全机制,提高了性能 JE是对标准版进行功能扩展,提供一系列功能,用来解决进行企业应用开发中所面临 的复杂的问题。具体的我们会放到后面JFE的课程去讲。 4:三个版本之间的关系 JE几乎完全包含JSE的功能,然后在JSE的基础上添加了很多新的功能。 JME主要是JSE的功能子集,然后冉加上一部分额外添加的功能 PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 如下图所示 JEE JSC JME Java的API类库之中有一组所谓的核心类( Corellas,即java.*),在核心类之外还有 所谓的扩允类( xtended Class,即 Javax.*)。根据对这两种类的支持程度,进而区分出几 种不同的Java版本。 我们必须以 Java Standard Edition(JSE)作为基准,这个版本做了所有Java标准规格 之中所定义的核心类,也文持所有的Java基木类。JSE定位在客户端程序的应用上 从JSE往外延伸,其外面为 Java Entcrprise edition(JEE),此版本除了支持所有的 标准核心类外,而且还增加了许多文持全业内部使用的扩充类,攴持 Servlet/JSP的 Javax. servlet.*类、支持 Enterprise Java Bean的 javax.ejb.*类。当然,JE必定支 持所有的Java基本类。JE定位在服务器端( server-side)程序的应用上。 从J5E向内看,是 Java micro edition(JME),它所支持的只有核心类的了集合,在JME CLDC的规格之中,只支持java.lang.*、java.io.*、以及java.uti1.*这些类。此版本 也增加了一些攴持“微小装置”的扩充类,如 Javax. microedition.io.*类。然而,此版 木并不支持所有的Java基木类,就标准的 JMECLDO,也就是能在 Palmos上执行的 KwM( KVirtualmachine)来说,它就不支持属于浮点数( float、 double)的Java基本类。JME 定位在嵌入式系统的应用上 最里层,还有一个Java的 Smart card版本,原本在Java的文件之中并没有这样定义 但是将亡画在JⅦ内部是很合理的。因为 SmartCard版本具攴持java.lang*这个核心类, 比起JM所支持的核心类更少,但它也有属」自凵的扩充类,如 Javacard.*、 javacard. 这些类 Smartcard版本只支持 Boolean与Bytc这两种Java基本类,此版本定位在 SmartCard 的应用上 四:闲话 ava 1:Java历史 在上世纪90年代初,sun公司有一个叫做 Green的项目,目的是为家用消费电子广品 开发一个分布式代码系统,这样就可以对家用电器进行控制,和它们进行信息交流。詹姆 斯·高斯林( James Gosling)等人基于C+开发一种新的语言0 ak ( java的前身)。0ak是 种用于网络的精巧而安全的语言。Sun公司曾依此投标个交互式电视项目,但结果是被SGl 打败,Sun打算抛弃0ak。随着可联网的发展,Sun看到了0ak在计算机网络上的广阔应用 前景,于是改造0ak,在1995年5月以“Java”的名称正式发布,从此Java走上繁荣之路 当然提到Jaa历史,不得不提的一个故事就是Java的命名。开始“Oak”的命名是以 项目小组办公室外的树而得名,但是Oak商标被其他公司注册了,必须另外取一个名字 传说有天,几位Java成员组的会员正在讨论给这个新的语言取什么名字,当时他们止在 咖啡馆喝着Java(爪哇)咖啡,有一个人灵机一动说就叫Java怎杵,得到了其他人的赞同, 于是,Java这个名字就这样传开了。当然对于传说,了解一下就好了,不必过于认真 2:Java大事记 PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 作为学习Java的人士,对Java历史上发生的大事件有一个了解是应该的。 JDK〔 Java Software Develop kit):Java软件开发工具包。JIK是Java的核心,包 括了Java运行坏境,一系刎Java开发工具和Java基础的类库。目前主流的JDK是Sun公 同发布的JDK,除了Sun之外,还有很多公司和组织都开发了自己的JD,例如IBM公司开 发的JD,BA公司的 Jrocket,还有GN组织丌发的JDK等等。 时间 事件 1995年5月23日 Java语言诞生 1996年1月 第个 JDK-JDK1.0诞生 1997年2月18日 JDK1.1发布 1998年12月8日 Java2企业平台J2EE发布 1999年6月 Sun发布JaⅤa三个版本:标准版J2SF,企业 版J2EE,微型版JME 2004年9月30日 Javase50发布 2006年12月 Java se60发布 3:Java特点 简单地说,Java具有如下特点:简单的、面向对象、平台无关、多线程、分布式、安全、 晑性能、可靠的、解释型、自动垃圾回收等特点。 这里只解释一下平台无关和分布式,其余的在后面会逐步接触到 3:平台无关 所谓平台无关指的是:用Java写的程序不用修改就可在不同的软硬件平台上运行。这 烊就能实现同样的程序既可以在 Windows下运行,到了Unix或者 Linux环境不用修改就直 接可以运行了。Java主要靠Java虚拟机(JⅧM)实现平台无关性 平台无关性就是一次编写,到处运行: Write Once, Run Anywhere 32:分布式 分布式指的是:软件由很多个可以独立执行的模块组成,这些模块被分布在多台计算机 上,可以同时运行,对外看起来还是个整体。也就是说,分布式能够把多台计算机集合起 来就像一台计算机一样,从而提供更好的性能 4:Java标准组织—Cp JCP( Java Community process)是一个开放的国际组织,成立于1995年,主要职能 是发展和更新Java技术规范、参考实现(RⅠ)、技术兼容包(TCK)。Java技术和JCP两者 的原创者都是SN计算机公司。组织成员可以提交JSR( Java Specification Requests), 通过讨论、认可、审核以后,将进入到下一版本的规范里面。 也就是说JCP是目前Java技术发展事实上的控制者和领导者。 五:Java如何做到让机器理解我们想要做的东西 用·个图来描述这个过程会比较谷易理解: PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 Runtime Compile Class loader Byte code Verifier Javac Hello.java Netwo Hello class Interpreter code Runtime generator/ Hardware 1:编写代码 首先把我们想要计算机做的事情,通过Java表达出来,写成Java文件,这个过程就是 编写代码的过程。如上图所示的 Hello java文件。 2:编译 写完Jaa代码后,机器并不认识我们写的Java代码,需要进行编译成为字节码,编译 后的文件叫做clas文件。如上图所示的 Hello, class文件。 3:类装载 Classloader 类裝载的功能是为执行程序寻找和装载所需要的类 Classloader能够加强代似的安全性,主要方式是:把本机上的类和內络资源类相分离, 在调入类的时候进行检查,因而可以限制任何“特洛伊木马”的应用。 4:字节码(byte-code)校验 功能是对 class文件的代码进行校验,保证代码的安全。 Java软件代码在实际运行之前要经过几次测试。JWM将代码输入一个字节码校验器以 测试代码段格式并进行规则检査一一检査伪造指针、违反对象访问权限或试图改变对象类型 的非法代码。 注意-—所有源于网络的类文件都要经过字节码校验器 字节码校验器对程序代码进冇四遍校验,这可以保证代码符合JⅧM规范并∏不破坏系统 的完整性。如果校验器在完成四遍校验后未返回出错信息,则下列各点可被保证 类符合JWⅦM规范的类文件格式 无访问限制异常 代码木引起操作数栈上溢或下溢 所有操作代码的参数类型将总是正确的 无非法数据转换发生,如将整数转换为对象引用 对象域访问是合法的 5:解释( Interpreter) 可是机器也不能认识clas文件,还需要被解释器进行解释,机器才能最终理解我们所 要表达的东西 PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 6:运行 最后由运行环境屮的 Runtime对代码进行运行,真正实现我们想要机器完成的工作 7:说明 由上面的讲述,大家看到,Java通过个编译阶段和个运行阶段,来让机器最终坦解 我们想要它完成的工作,并按照我们的要求进行运行 在这两个阶段屮,需要我们去完成的就是编译阶段的工作,也就是说:我们需要把我们 想要札器完成的工作用Jaa语言表达出来,写成Java源文件,然后把源文件进行编译,形 成 class文件,最后就可以在JaⅦa运行环境中运行了。运行阶段的工作由Java平台自身提供 我们不需要做什么上作。 六:Java技术三大特性 1:虚拟机 Java虚拟机JM( Java Virtual Machine)在Java编程里面具有非常重要的地位,约 相当于前面学到的Java运行环境,虚拟机的基本功能如下: (1):通过 Classloader寻找和装载 class文件 (2):解释字节码成为指令并执行,提供 class文件的运行环境 (3):进行运行期间垃圾回收 4):提供与硬件交互的平台 Java虚拟杋是在真实札器中用软件模拟实现的—种想象机器。Jaa虚拟札代码被存储 在.clas文件中;每个文件都包含最多一个 public类。Java虚拟机规范为不同的硬件平台 提供了·种编译Java技术代码的规氾,该规范使Java软件独立于平台,因为编译是针对作 为虚拟机的“一般机器”而做。这个“一般机器”可用软件模拟并运行于各种现存的计算机 系统,也可用硬件米实现ε编译器在获取Java应用程序的源代码后,将其生成字节码,它是 为J硎M生成的一种机器码指令。每个Java解释器,不管它是Java技术廾发工具,还是可运行 applets的Wcb浏览器,都可执行JVM。 JWM为下列各项做出了定义 指令集(相当于中央处理器[CP]) 寄存器 类文件格式 栈 垃圾收集堆 存储区 JⅧM的代码格式由紧缩冇效的字节码构成。由J硎M字节码编写的程序必须保持适当的类 型约東。大部分类型检査是在编译时完成。任何从属的Java技术解释器必须能够运行仼何 含有类文件的程序,这些类文件应符合Java虚拟机规范中所指定的类文件格式 1.1:虚拟机是Java平合无关的保障 正是因为有虚拟机这个中间层,Java才能够实现与平台无关。虚拟机就好比是一个Java 运行的基本平台,所有的Java程序都运行在虚拟机上,如下图所示: PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 Java源程序(*java文件) Javac编译 ava类文件(*cass文什) 平台无 被装载进入虚拟机 Java虚拟机 平台相关 解释执行字节码文件 Linux Windows 2:垃圾回收 2.1:什么是垃圾 在程序运行的过程中,存在被分配了的内存块不再被需要的情况,那么这些内存块对程 序来讲就是垃圾。 产生了垃圾,自然就需要清理这些垃圾,更为重要的是需要把这些垃圾所占用的内存资 源,回收回来,加以再利用,从而节省资源,提高系统性能。 2.2:垃圾回收 不再需要的凵分配内存应取消分配(释放内存) 在其它语言中,取消分配是程序员的责仟 Java编程语言提供了种系统级线程以跟踪内存分配 垃圾攻集 可检查和释放不再需要的内存 可自动完成上述工作 可在JM实现周期中,产生意想不到的变化 许多编程语言都允许在程序运行时动态分配内存,分配内存的过程由于语言句法不同而 有所变化,但总是要将指针返回到内存的起始位置,当分配内存不再需要时(內存指针已溢 出范围),程序或运行环境应释放内存 在C,C艹+或其它语言中,程序员负责释放内存。有吋,这是件很困难的事情。因为 你并不总是事先知道内存应在何时被释放。当在系统中没有能够被分配的内有时,可导致程 序瘫痪,这种程序被称作具有内存漏洞 java编程语言解除∫程序员释放内存的贲仼。它可提供一种系统级线程以跟踪每一次 内存的分配情況。在Java虚拟机的空闲周期,垃圾收集线程检查并释敚那些可被释放的内 存。垃圾收集在Java技术程序的生命周期中自动进行,它解除了释放内存的要求,这样能 够有效避免内存漏洞和内存泄露(内冇泄露就是程序运行期间,所占用的内存一直往上涨, 很容易造成系统资源耗尽而降低性能或崩溃) PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:010-86835215 2.3:提示 (1):在Java里面,垃圾回收是一个自动的系统行为,程序员不能控制垃圾回收的功 能和行为。比如垃圾回收什么时候开始,什么时侯结束,还有到底哪些资源需要回收等,都 是程序员不能控制的 (2):有些跟垃圾回收相关的方法,比如: System. gc(,记住“点,调用这些方法, 仅仅是在通知垃圾回收程序,全于垃圾回收程序运个运行,仆么时候运行,都是尢法控制的。 (3):程序员可以通过设置对象为nul(后面会讲到)来标示某个对象不再被需要了, 这只是表示这个对象可以被回收了,并不是马上被回收 3:代码安全 Java如何保证编写的代仍是安全可靠的呢? (1):第一关:编写的代码首先要被编译成为 class文件,如果代码写得有问题,编译期间 就会发现,然后提示有编译错误,无法编译通过。 (2):第二关:通过编译关后,在类装载的时候,还会进行类装载检查,把本机上的类和网 络资源类相分离,在调入类的时候进行检査,因而可以限制仁何“特洛伊木马”的应用 (3):第三关:类装载后,在运行前,还会进行字节校验,以判断你的程序是安全的。 (4):第四关:如果你的程序在网终上运行,还有沙箱( Sand box)的保护,什么是沙箱呢? 就是如果你的程序没有汏得授权,只能在沙箱限定的范围内运行,是不能够访问本地資源的, 从而保证安全性。 如下图所示: Runtime Compile Java class Loader匿载检查 Hello world. java Network Byte code verifier 节码校验 Javac 编译检耷 Hello World class Interpreter Runtime Hardware 学习到这甲,大家应该对Java有了一定的了解了。现在是否想要看看Java程序究竟什 么样子呢?是不是想要体会一下如何开发Java程序呢?下面我们先米看看如何构建JSE的 环境,这是进行Java程序开发的第一步, PDF文件使用" pdfFactory Pro"试用版本创建ww, fineprint,cn
netstat 命令 netstat是用来显示网络的连接,路由表和接口统计等网络的信息.netstat有许多的 选项 我们常用的选项是 -an 用来显示详细的网络状态.至于其它的选项我们可以使用帮 助手册获得详细的情况. telnet telnet是一个用来远程控制的程序,但是我们完全可以用这个程序来调试我们的服务端程 序的. 比如我们的服务器程序在监听 8888 端口,我们可以用 telnet localhost 8888来查 看服务端的状况. TCP(Transfer Control Protocol)传输控制协议是一种面向连接的协议,当我们的网络程 序使用 这个协议的时候,网络可以保证我们的客户端和服务端的连接是可靠的,安全的. UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议,这种协议并不能保证 我们的网络程序的连接是可靠的,所以我们现在编写的程序一般是采用 TCP协议的 socket int socket(int domain, int type,int protocol) domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX 和AF_INET 等). AF_UN IX 只能够用于单一的 Unix 系统进程间通信,而 AF_INET 是针对Internet的,因而可以允许在 远程 主机之间通信(当我们 man socket 时发现 domain 可选项是 PF_*而不是AF_*,因为 glibc 是 posix 的实现 所以用 PF代替了 AF,不过我们都可以使用的). type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM 等) SOCK_STREAM 表明 我们用的是 TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是 UDP协议,这样只会提供定长的,不可靠,无连接的通信. protocol:由于我们指定了 type,所以这个地方我们一般只要用 0 来代替就可以了 sock et 为网络通讯做基本的准备.成功时返回文件描述符,失败时返回-1,看 errno 可知道出错 的详细情况. bind int bind(int sockfd, struct sockaddr *my_addr, int addrlen) sockfd:是由socket调用返回的文件描述符. addrlen:是 sockaddr结构的长度. my_addr:是一个指向 sockaddr的指针. 在<linux/socket.h>;中有 sockaddr的定义 struct sockaddr{ unisgned short as_family; char sa_data[14]; }; 不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sock addr_in) 来代替.在<linux/in.h>;中有 sockaddr_in 的定义 struct sockaddr_in{ unsigned short sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; 我们主要使用 Internet所以 sin_family 一般为 AF_INET,sin_addr设置为 INADDR_ANY 表 示可以 和任何的主机通信,sin_port 是我们要监听的端口号.sin_zero[8]是用来填充的 .. bind 将本地的端口同 socket返回的文件描述符捆绑在一起.成功是返回 0,失败的情况和 socket一样 listen int listen(int sockfd,int backlog) sockfd:是 bind 后的文件描述符. backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示 可以介绍的排队长度. listen函数将 bind 的文件描述符变为监听套接字.返回的情况和 b ind 一样. accept int accept(int sockfd, struct sockaddr *addr,int *addrlen) sockfd:是 listen后的文件描述符. addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,li sten和 accept是服务器端用的函数,accept调用时,服务器端的程序会一直阻塞到有一个 客户程序发出了连接. accept 成功时返回最后的服务器端的文件描述符,这个时候服务 器端可以向该描述符写信息了. 失败时返回-1 connect int connect(int sockfd, struct sockaddr * serv_addr,int addrlen) sockfd:socket返回的文件描述符. serv_addr:储存了服务器端的连接信息.其中 sin_add 是服务端的地址 addrlen:serv_addr的长度 connect函数是客户端用来同服务端连接的.成功时返回 0,sockfd 是同服务端通讯的文件 描述符 失败时返回-1. 总的来说网络程序是由两个部分组成的--客户端和服务器端.它们的建立步骤一般是: 服务器端 socket-->;bind-->;listen-->;accept 客户端 socket-->;connect 字节转换函数 在网络上面有着许多类型的机器,这些机器在表示数据的字节顺序是不同的, 比如 i386 芯 片是低字节在内存地址的低端,高字节在高端,而 alpha 芯片却相反. 为了统一起来,在 Li nux 下面,有专门的字节转换函数. 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 第一个函 数的意义是将本机器上的 long 数据转化为网络上的 long. 其他几个函数的意义也差不多 .. IP 和域名的转换 在网络上标志一台机器可以用 IP或者是用域名.那么我们怎么去进行转换呢? struct hostent *gethostbyname(const char *hostname) struct hostent *gethostbyaddr(const char *addr,int len,int type) 在<netdb.h>;中有 struct hostent的定义 struct hostent{ char *h_name; /* 主机的正式名称 */ char *h_aliases; /* 主机的别名 */ int h_addrtype; /* 主机的地址类型 AF_INET*/ int h_length; /* 主机的地址长度 对于IP4 是 4 字节 32 位*/ char **h_addr_list; /* 主机的 IP地址列表 */ } #define h_addr h_addr_list[0] /* 主机的第一个 IP地址*/ gethostbyname 可以将机器名(如 linux.yessun.com)转换为一个结构指针.在这个结构里 面储存了域名的信息 gethostbyaddr可以将一个 32 位的 IP地址(C0A80001)转换为结构指针. 这两个函数失败时返回 NULL 且设置 h_errno 错误变量,调用 h_strerror()可以得到详细的 出错信息 字符串的 IP 和 32位的 IP 转换. 在网络上面我们用的 IP都是数字加点(192.168.0.1)构成的, 而在 struct in_addr结构中 用的是 32 位的 IP, 我们上面那个 32 位IP(C0A80001)是的 192.168.0.1 为了转换我们可以 使用下面两个函数 int inet_aton(const char *cp,struct in_addr *inp) char *inet_ntoa(struct in_addr in) 函数里面 a 代表 ascii n 代表 network.第一个函数表示将 a.b.c.d 的 IP转换为 32 位的 I P,存储在 inp 指针里面.第二个是将 32 位 IP转换为 a.b.c.d 的格式 服务信息函数 在网络程序里面我们有时候需要知道端口.IP和服务信息.这个时候我们可以使用以下几 个函数 int getsockname(int sockfd,struct sockaddr *localaddr,int *addrlen) int getpeername(int sockfd,struct sockaddr *peeraddr, int *addrlen) struct servent *getservbyname(const char *servname,const char *protoname) struct servent *getservbyport(int port,const char *protoname) struct servent { char *s_name; /* 正式服务名 */ char **s_aliases; /* 别名列表 */ int s_port; /* 端口号 */ char *s_proto; /* 使用的协议 */ } 一般我们很少用这几个函数.对应客户端,当我们要得到连接的端口号时在 connect调用成 功后使用可得到 系统分配的端口号.对于服务端,我们用 INADDR_ANY 填充后,为了得到连 接的 IP我们可以在 accept 调用成功后 使用而得到IP地址. 在网络上有许多的默认端口和服务,比如端口 21 对 ftp80 对应 WWW.为了得到指定的端口号 的服务 我们可以调用第四个函数,相反为了得到端口号可以调用第三个函数.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值