Java核心技术卷II(第8版) – 读书笔记 – 第3章

本章是重头戏:网络编程!

1、首先测试一下daytime服务:

这个过程中,DNS将ntp.glb.nist.gov解析为IP地址,然后TCP连接端口13,接下来反复读取、交换数据,直到连接关闭。

2、用基本的Java的Socket模拟上述过程:

3、上述代码,首先构造Socket,创建一个套接字。
如果失败会抛出各种异常,如UnknownHostException(解析错误)或者IOException(其他错误)。
然后通过getInputStream获取InputStream,这是从远程到本机的“数据管道 ”。

4、上述例子很简单,因为只有服务器主动向客户发送数据,之后就关闭了。一般的通信,是需要客户和服务器双方交互并进行复杂的协议规定。

5、在Socket建立起连接之后,InputStream的read可能需要一定的等待时间才能得到数据。对于有的应用,这是不可接受的,或者说这个的等待时间需要有上限,我们可以设置这个timeout时间:

注意单位是ms,而且这个只对read()操作有效。

6、对于connect()(在Java对应的是构造Socket的过程),那么需要单独的使用connect来实现:

7、IPV4地址为4个字节,IPV6地址为16个字节。Java支持V4和V6地址。解析域名到IP地址:

一些网站都会在一个域名上设置多个IP地址,以达到负载均衡,上面这个getAllByName就是可以取到全部的IP地址,比如google的有如下结果:

8、如果想要获得本机IP地址,可以用:

9、下面是创建一个最简单的网络服务器端的步骤:
(1)建立ServerSocket s = new ServerSocket(8888)
(2) Socket incoming = s.accept();
(3) income就是客户了,在此基础上进行交互,执行相应的逻辑,使用input/outputstream。
(4)关闭income的socket。

上面的逻辑部分,我们使用最简单的Echo,即客户发送什么,我们回显什么。

我这里直接用的最裸的inputstream/outputstream,直接read/write了,没有用PrintWriter神马的。

10、上面这个Server有个问题,多个client同时请求时候,后面的会被hold住(挂起)。。。肿么办?最简单的是多线程搞起,一个新client给开一个新线程处理:

但是这种的效率不会特别高,建议尽量用nio的一些特性。

11、半关闭:套接字连接的一端终止其输出,同时仍旧可以接受来自另外一端的数据。应用场景,例如:我们要向服务器端发送数据,但不知道一共要传输多少。可以一直发送,发送后关闭写通道(但要保持读通道开启)。此时服务器端将会知道这一事件,做出对应处理。

12、半关闭适用于“一站式”协议,如HTTP,客户发送一个请求,然后服务器也回送一个响应。这时用半关闭很好:

13、在交互式网络协议中,想实现“如果某个连接长期没有响应,变中止它”。这种需要用nio的SocketChannel来辅助实现。

然后在需要中断的时候:

thread.interrupt()就可以了,对应的OutputStream会退出,因为这个创建出来的是interruptible I/O。

14、发送E-Mail的例子。

SMTP协议发送E-Mail实际是客户端,相当于Foxmail等。

协议:

HELO sending host
MAIL FROM: <Sender email>
RCPT TO: <Recp email>
DATA
xxxx
xxxx
.
QUIT

每一行都是\r\n换行。

没什么特别的。。JDK已经有JavaMail提供了很完善的功能。

15、如果要进行更高层次的开发,如HTTP,可以考虑URL类。

和它长的很像的还有一个URI,这主要是用于记录地址的,比如:

mailto:xxx@xx.com、http://www.xxx.com

URI的格式是规定好的:

[schema]schemaSpcificPart[#fragmant]

可以使用“相对化”处理层次的URI。

16、如果要抓起Web页面,可以直接用URLConnection。

(1)URL url = …
(2)conn = url.OpenConnection()
(3)conn.setXXX(UseCache/Modify/ReadTimeout)等HTTP请求的属性。
(4)conn.connect()
(5)连接之后,可以getContentType/getContentLength/…查询Response中HTTP的标准字段,也可以getHeaderFieldKey和getHeaderField来枚举所有的头。
(6)读、写用getInputStream和getOutputStream搞定。

下面是一个基本的例子,抓取网页,打印response中的字段。

17、如果要发送表单神马的必须conn.setDoInput(true) 。

18、定制请求头,conn.setRequestProperty():

19、下面是一个向一个支持POST的页面发送POST的例子。

本章完毕。

(Java核心技术对于网络这部分不给力啊。。UDP、NIO都没写,改天找找资料自己补上)

 

 

Leave a Reply

Your email address will not be published.