有关java网络开发相关笔记

java网络编程

端口:

端口是用来区分应用程序,这些都是对计算机内存的抽象,每个端口在1到65535之间的数字标识,每个端口可以分配给一个特定的服务

1-1023的端口号保留给已知的服务


防火墙

在本地网络建立一个访问点,检查所有进出访问点的业务流通很有用,位于Internet和本地网络之间的一些硬件和软件会检查所有进出的数据,以保证其合法性,这就是防火墙,过滤通常是基于网络地址和端口


代理服务器

代理服务器与防火墙有关,防火墙会阻止一个网络上的主机与外界直接建立连接,代理服务器就起到了中间人的作用,防火墙一般工作于传输层或网络层,而代理服务通常工作于应用层,可以检查通过代理服务器的包,确保其中包含适当类型的数据

代理服务器最大的问题在于它无法应对所有协议(通常已有的协议有http,ftp,smtp),但对于更新的协议就不允许通过,使用java可以很容易创建应用而优化的新协议(开发人员开始通过http来接入它们的协议,如SOAP,不过,这对安全性有明显的负面影响,防火墙的存在肯定事出有因,而不只是找java程序员的麻烦)

(xxx.proxyhost,xxx.proxyport,xxx.proxyset)系统属性,来指示使用的代理服务器


客户/服务器模型

大多数现代网络编程都基于客户/服务器模型,客户/服务器应用程序一般将大量数据存储在昂贵的高性能服务器或服务器云上,而大多数程序逻辑和用户界面由客户端软件处理


Internet标准

关注某个协议的详细信息,权威的资源还是该协议的标准文档

世界上有很多标准组织,但关于应用层网络编程和协议大多数标准都由下面两个组织制定它们为IETF和W3C,前者是非正式团体,多数人说了算,后者是厂商,后者有钱

(能不能自己制定标准呢,用于秘密使用,而不是公开出来,答案是可以的,不然哪里来的internate)


IETF RFC

IETF标准和接近标准公布为"征求意见",这个实际上已经完成工作,一旦发布就无法被改动;可以修改并允许开发的IETF文档称为Internet草案

RFC可以从网上很多位置下载

(那么底层是如何支撑这些协议来着呢,如果不遵守这些约定又会发生什么事情)


网络程序所做的很大部分工作都是简单的输入和输出,java的输入和输出是建立在i/o流之上的,不同的流读取特定的数据源,输出流都是相同基本方法写入数据。过滤器流可以串联道输入和输出流上,过滤器可以修改数据。

阅读器和书写器可以串联道输入流和输出流上,允许程序读文本字符而不是字节。

流是同步的,也就是当它要进行读写一段数据时,那么它也就只能是做等待读或写,java还支持甬道和缓冲区的非阻塞i/o,在某些高吞吐量的服务器中,非阻塞i/o要快得多

甬道和缓冲区都是依赖于流的


输出流

java.io.outputstream.

这个类提供写入数据所需的基本方法,这些方法包括

write(int b),write(byte[]b),write(byte[] d,int offset,int length),flush(),close()

outputstream的子类使用这些方法像某种特定介质写入数据

如果是将数据发送到网络通常是会被缓存数据达到一定数量才会被发送,但数量达不到就会陷入死锁中,所以就有了flush方法

try(){}
catch(){
    
}

像上面的写法就可以自己释放资源,而不用自己调用close方法


public abstract class inputstream

这类提供了将数据读取为原始字节所需的基本方法,这些方法包括:

int read(), int red(byte[] input),int read(byte[] input,int offset,int length),skip(long n),int available(),void close()

inputstream的具体子类使用这些方法从某种特定介质中读取数据

fileinputstream,telnetinputstream,bytearrayinputstream,分别是从文件中读取数据,从网络连接中读取数据,从字节数组中读取数据

inputstream的基本方法是没有参数的read方法,这个方法从输入流的源中读取1字节数据,作为0到255的int返回,流的结束通过返回-1来表示,也就是读的这个字节,返回也就是这个字节,在0到255的int表示,read()方法会等待并阻塞其后任何代码的执行

(有符号与无符号,从有符号转化为无符号)

如果不想等待所需的全部字节都立即可用,可以使用avilable()方法来确定不阻塞的情况下有多少字节可以读取

在少数情况下,您可能希望跳过数据不进行读取。skip方法会完成这项任务,与读取文件相比,在网络连接中它的用处不大

当结束对输入流的操作,应当调用它的close方法将其关闭


标记和重置

inputstream类还有3个不太常用的方法,允许程序备份和重新读取已经读取的数据

public void mark(int readaheadlimit)

public void reset() throws ioexception

public boolean marksupported()

为了重新读取数据,要用mark方法标记流的当前位置,在以后某个时刻,可以用reset方法把流重置到之前标记的位置,接下来的读取操作会返回从标记位置开始的数据,不过,不能随心所欲地向前重置任意远的距离,由mark的readaheadlimit参数

标记和重置通常通过将标记位置之后的所有字节存储在一个内部缓冲区中来实现,不过,不是所有输入流都支持这一点,不是所有的流都支持标记和重置的要用marksupported方法是否返回true,如果返回true,就表明这个流支持标记和重置。

过滤器流

(个人不太喜欢这个名字,更喜欢叫为处理流)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOj5E0sU-1617450031083)(E:\照片\2021-04-03_105916.png)]

inputstream和outputstream是相当原始的类,它们可以单个或成组地读/写字节,但仅此而已,要确定这些字节的含义,完全由程序员和代码来完成,java提供了很多过滤器类,可以附加到原始流中,在原始字节和各种格式之间来回转换,过滤器有两个版本,过滤器流以及阅读器和书写器,过滤器流主要将原始数据作为字节处理,例如通过压缩或解释为二进制数字,阅读器和书写器处理多种编码文本的特殊情况,如utf-8,iso 8859

过滤器以链的形式进行组织,链中的每个环节都接收前一个过滤器或流的数据,并把数据传递给链中的下一个环节

将过滤器串链在一起

过滤器通过其构造函数与流连接

FileInputStream fin=new FileInputStream("data.txt");
BufferedInputStream bin=new BufferedInputStream(fin);
Inputstream in=new fileInputstream("data.txt");
in=new BufferedInputStream(in)

如果要使用超类中没有的方法

DataOutputStream dout=new DataOutputStream(new BufferedOutputStream(new fileOutputStream("data.txt")))

缓冲流

BufferedOutputStream类将写入数据在缓冲区中(一个名为buf的保护字节数组字段),直到缓冲区满或刷新输出流,然后它将数据一次全部写入底层输出流,·缓冲网络输出通常会带来巨大的性能提高

​ BufferedInputStream类也有一个作为缓冲区的保护字节数组,名为buf,当调用某个流的read()方法时,它首先尝试从缓冲区获取请求的数据,只有当缓冲区没有数据时,流才从底层的源中读取数据,这时它从源中读取尽可能多的数据存入缓冲区,而不管是否马上需要所有这些数据。不会立即用到的数据可以在以后调用read时读取。当从本地磁盘中读取文件时,从底层流中读取几百个字节的数据与读取1字节数据几乎一样快,因此缓冲可以显著提升性能,对于网络连接,这种效果则不甚明显,在这里瓶颈往往是网络传送数据的速度,缓冲输入没有什么坏处,随者网络的速度加快会变得更为重要。

public bufferedinputstream(inputstream in)
public bufferedinputstream(inputstream in,int buffersize)
public bufferedoutputstream(outputstream out)
public bufferedoutputstream(outputstream out,int buffersize)    

这写方法的参数应该从其功能来定比如输入流,就是将输入读到缓冲区,或者向其写入缓冲的数据,如果给第二个参数,它会指定缓冲区的字节数,默认缓冲区大小设置为2048字节,输出流的缓冲区设置为512字节,缓冲区的理想大小取决所缓冲的流是何种类型,对于网络连接,你会希望比一般的包大小更大一些。

BufferedInputStream没有声明自己的任何新方法,它只覆盖了InputStream的方法,它支持标记和重置。两个多字节read方法尝试根据需要多次从底层输入流取数据。从而完全填充指定的数组

PrintStream

printstream类是大多数程序员都会遇到第一个过滤器输出流,因为system.out就是一个printstream,不过,还可以使用下面两个构造函数将其他输出流串链到打印流

public printStream(outputstream out)
public printStream(outputstream out,boolean autoflush)    

printstream是有害的,网络程序员应当像躲避瘟疫一样避开它

第一问题,就是在隔行时,需要隔行符分隔,对于明确协议的网络客户端和服务器而言,大多数网络协议明确指定行应当以回车/换行对结束,使用println()写出程序有可能在window上正常工作,在unix和mac无法工作,许多服务能够放宽地接受而且处理不正确的行解释符,但偶尔有例外

第二个问题,会使用平台的默认编码方式,这种编码方式可能不是服务器或客户端所期望的

第三个问题,printstream吞掉了所有异常

所以printstream提供的错误通知对于不可靠的网络连接来说远远不够


数据流

datainputstream和dataoutputstream类提供一些方法,可以用二进制读/写java的基本数据类型和字符串,二进制格式主要用于在两个不同的java程序之间交换数据(网络连接,数据文件,管道,或其他中间介质),java和大多数网络协议都是由unix程序员设计,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aADp4pxP-1617450031102)(E:\照片\2021-04-03_155354.png)]


阅读器和书写器

许多程序员在编码时有一个坏习惯,好像所有文本都是ASCII,或者至少该平台的内置编码方式。但对于http和其他很多更新的协议却不是这样,它们允许多种本地化编码。

java的内置字符集是unicode的utf编码,当编码不再是ASCII时,如果嘉定字节和字符实质上是一致的,这也会出问题,因此对应输入和输出流类层次体系,java提供了一个基本上完整的镜像,用来处理是字符而不是字节

这个镜像体系中,两个抽象超类定义了读/写字符的基本API,Java.io.Reader类指定读取字符的API。Java.io.Writer来写字符的API,阅读器和书写器会使用Unicode字符,Reader和Writer的具体子类允许读取特定的源与写入特定的目标,过滤器阅读器和书写器可以附加到其他阅读器或书写器上,以提供额外的服务或接口。

reader和writer最重要的具体子类是inputstreamreader,outputstreamwriter类,inputstreamreader类包含一个底层输入流,可以从中读取原始字节,它根据指定的编码方式,将字节转换程unicode字符,outputstreamwriter从运行的程序中接收为unicode字符,然后使用指定的编码方式将这些字符转化为字节,再将这些字符写入底层输入流中。

filereader

filewriter

stringreader

stringwriter

chararrayreader

chararraywriter

以上所列的前两个类可以处理文件,后四个由java内部使用,所以在网络编程不太正常

书写器

writer类是java.io.outputstream类的映射,它是一个抽象类,有两个保护类型的构造函数,与outputstream类似,writer类从不直接是使用,相反,会通过它的某个子类以多态方式使用

protected writer();
protected writer(object lock);
public abstract void write(char[] text,int offset,int length);
public void write(int c);
public void write(char[]text);
public void write(string s);
public void write(string s,int offset,int length);
public abstract void flush();
public abstract void close();

outputstreamwriter

outputstreamwriter是writer的最重要的具体子类,会从outputstreamwrite会从java程序接收字符,它根据指定的编码方式将这些字符转换为字节,并写入底层输出流

public outputstreamwriter(outputstream out,string encoding);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值