Java网络编程技术.docx
- 文档编号:30376765
- 上传时间:2023-08-14
- 格式:DOCX
- 页数:24
- 大小:340.88KB
Java网络编程技术.docx
《Java网络编程技术.docx》由会员分享,可在线阅读,更多相关《Java网络编程技术.docx(24页珍藏版)》请在冰豆网上搜索。
Java网络编程技术
java
Java网络编程技术
本章将介绍Java网络方面的基础概念。
然后介绍编写连接网络的Java程序。
最后,我们还将介绍如何访问Internet上的信息。
一、连接到服务器
在编写网络程序之前,我们先了解一下telnet这个工具。
大多数的系统(包括Linux和windows)都安装了telnet。
我们以windows为例来熟悉telnet工具。
(1)首先,打开windows的
应用。
(2)然后,在窗口中输入telnet192.168.0.23480这样就可以连接到指定IP地址的机器上。
屏幕显示如图所示:
(3)输入“y”,按回车键后,屏幕提示输入系统的用户名与密码。
屏幕显示如图所示:
(4)输入系统正确的用户名与密码,按回车键后进入指定IP地址的系统。
在网络术语中,端口指的并不是物理设备,而是为了便于实现服务器与客户端之间通信所使用的概念。
二、实现服务器
下面我们实现一个简单的服务器,它可以接收客户端发送信息,经过处理后返还给客户端。
启动服务器,它便等待某个客户端的请求连接服务器的端口,我们选择端口8378,这个端口并不被系统服务占用。
案例1:
客户端与服务端通信
示例代码的功能介绍。
每一个服务器程序,比如一个HTTPWeb服务器,都不间断地执行下面这个循环操作:
(1)通过输入数据流从客户端接受一个命令。
(2)通过某种方式获取信息
(3)通过输出数据流给客户端发送信息。
程序代码:
服务端程序EchoServer.java
客户端程序SocketTest.java
知识点:
●ServerSocket(intport)
所在.ServerSocket。
用于创建一个监控端口的服务器套接字。
●Socketaccept()
等待连接。
该方法阻塞当前线程直到建立连接为止。
该方法返回一个套接字对象,程序可以通过这个对象与连接中的客户端进行通信。
●voidclose()
关闭服务器套接字。
案例2:
为多个客户端服务
我们可能希望有多个客户端同时连接到我们的服务器上。
通常,服务器总是不间断地运行在服务器计算机上,来自整个网络的用户希望同时使用服务器。
我们可以运用多线程把这个问题解决好。
每当程序建立一个新的套接字连接,也就是说当accept被成功调用的时候,将创建一个新的线程来处理服务器和该客户端之间的连接。
主程序将立即返回并等待下一个连接。
程序代码:
服务端程序ThreadEchoServer.java
服务端线程ThreadedEchoHandler.java
客户端程序SocketTest.java
三、建立URL连接
本节介绍Java平台所提供的更高级别的服务。
运行时的类库是使用套接字来实现服务的,但是当使用这些类库提供的高层服务时,并不需要考虑协议的实现细节。
3.1URL和URI
URL和URLConnection类封装了大量复杂的实现细节,这些细节涉及如何从远程站点获取信息。
可以通过传递字符串来构建一个URL对象:
URLurl=newURL(urlString);
如果总是想获得该资源的内容,可以使用URL类中的openStream方法。
该方法返回一个InputStream对象,然后就可以按照一般的做法来使用这个对象了,比如用它构建一个Scanner对象:
InputStreaminStream=url.openStream();
Scannerin=newScanner(inStream);
JDK1.4开始,包对统一资源定位符(URL)和统一资源标识符(URI)作了非常有用的区分。
URI是个纯粹的句法结构,用于指定标示Web资源的字符串的各个不同部分,URL是URI的特例,它包含了定位web资源的足够信息。
其他URI,比如:
mailto:
cay@
则不属于定位符,因为根据该标识符我们无法定位任何数据。
像这样的URI我们称之为URN(统一资源名称)
在Java类库中,URI类不包含任何用于访问资源的方法——它的惟一作用就是解析。
相反的是,URL类可以打开一个到达资源的流。
因此,URL类只能作用于那些Java类库知道该如何处理的模式,例如:
http:
、ftp:
等
为什么对URI进行解析不是可有可无的,要考虑到它也许会变得非常复杂。
例如:
ftp:
//username:
password@
URI规范给出了标记这些标识符的规则。
一个URI具有以下句法:
[schema:
]schemeSpecificPart[#fragment]
上式中,[…]表示可选部分,它与:
和#可以被包含在标识符内。
包含schema:
部分的URI被称为绝对URI。
否则,被称为相对URI。
如果绝对URI的schemaSpecificPart不是以/开头的,我们就称它是不透明的。
例如:
mailto:
cay@
所有绝对的透明URI和所有相对URI都是分层的。
例如:
./index.html
../java/net/Socket.html#Socket
一个分层URI的schemaSpecificPart具有以下结构:
[//authority][path][?
query]
在这里,[…]同样表示可选部分。
对于那些基于服务器的URI,authority部分采用以下形式:
[user-info@]host[:
port]
port必须是一个整数。
URI类的作用之一是解析标识符并将它分解成各种不同的组成部分。
可以用以下方法读取它们:
getSchema
getSchemaSpecificPart
getAuthority
getUserInfo
getHost
getPort
getPath
getQuery
getFragment
URI类的另一个作用是处理绝对标识符和相对标识符。
如果存在一个如下的绝对URI:
和一个相对URI:
../java/net/Socket.html#Socket
那么可以将它们合并成一个绝对URI:
java/net/Socket.html#Socket
这个过程被称为相对URL转换。
与此相反的过程称为相对化。
例如:
和另一个URI:
那么相对化之后的URI就是:
net/ServerSocket.html
URI类同时支持以下两个操作:
relative=uri.relativize(URIu);
combined=uri.resolve(URIu);
combined=uri.resolve(Stringstr);
案例:
URL类的相对URL转换与相对化
通过案例演示怎样把一个相对路径转化为一个绝对路径,怎样把一个绝对路径转换为相对路径,并把转换后的路径结果打印在控制台上。
程序代码:
程序组类URLRlativeizeResolve.java
3.2使用URLConnection获取信息
如果想要获得web上的资源,那么应该使用URLConnection类,它比URL类功能更强。
下面我们演示一个使用URLConnection类连接Web远程服务器的案例。
案例:
URLConnection连接Web服务
可以进行URL连接。
程序运行起来后,请在启动命令行中输入一个URL以及可选的用户名和密码,例如:
usernamepassword
该程序将输出以下内容:
●消息头中的所有键和值;
●响应头方法的返回值;
●被请求资源的前10行信息。
程序代码:
程序主类URLConnectionTest.java
base64编码计算类Base64OutputStream.java
知识点:
●URLConnectionopenConnection()
与服务器建立套接字连接,并且可以用于向服务器查询头信息。
●URLConnectionconnect()
返回一个URLConnection对象,该对象负责管理与资源之间的连接。
●voidsetDoInput(booleandoInput)与booleangetDoInput()
如果doInput为true,那么用户可以接受来自该URLConnection的输入。
●voidsetDoOutput(booleandoInput)与booleangetDoOutput()
如果doOutput为true,那么用户可以将输出发送到该URLConnection。
●voidsetDoOutput(booleandoInput)与booleangetDoOutput()
如果doOutput为true,那么用户可以将输出发送到该URLConnection。
●voidsetReadTimeout(inttimeout)与booleangetReadTimeout()
设置读取数据的超时时间(单位:
毫秒)。
如果在一个读操作成功之前就已经达到了超时的时限,那么输入流read方法就会就会抛出一个SocketTimeoutException异常。
●voidsetConnectTimeout(inttimeout)与booleangetConnectTimeout()
设置或得到连接超时时限(单位:
毫秒)。
如果在一个连接建立之前就已经达到了超时的时限,那么connect方法就会就会抛出一个SocketTimeoutException异常。
●voidsetRequestProperty(Stringkey,Stringvalue)
设置请求头的一个字段。
●Map
返回响应的一个映射表。
相同的键对应的所有值被放置在用一个映射表中。
●StringgetHeaderFieldKey(intn)
得到响应头第n个字段的值。
如果n等于0或者大于响应头字段的总数,该方法返回null值。
●StringgetContentType()
获取内容的类型。
例如text/plain。
●intgetContentLength()
如果知道内容长度,则返回该长度值,否则返回-1。
●StringgetContentEncoding()
获取内容的编码,比如:
GB2312
●longgetDate()、longgetExpiration()和longgetLastModifed()
获取创建日期、过期日以及最后一次被修改的日期。
日期从1970年1月1日0点开始计算的秒数。
●InputStreamgetInputStream()
返回从资源读取信息的流。
Base64编码计算:
为什么要和0xFC做&操作呢?
第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符。
Base64编码原理:
3个8位2进制数拆分成4个6位2进制数拆分后,第一字节取原第一字节高6位拆分后,第二字节取原第一字节低2位和原第二字节高4位拆分后,第三字节取原第二字节低4位和原第三字节高2位拆分后,第四字节取原第三字节低6位。
BASE64字符表:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/根据拆分后的6位2进制数找到相应的字符。
当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。
这时在最后一组填充1到2个0字节。
并在最后编码完成后在结尾添加1到2个“=”
示例:
0xFC对应的二进制是11111100,意思就是取前6位(因为b的后2位被0与掉了),>>2表示右移2位,即取前6位buf[0]=(byte)((b&0xFC)>>2);0x03对应的二进制是00000011,即留前一个字符b的后2位,要左移4位,以便给下4位留个地方。
四、套接字编程
本节我们将介绍如何利用超时与中断来处理连接错误。
使用半关闭机制简化请求协议。
最后介绍因特网地址的相关内容。
4.1套接字超时
实际应用中,可能不想从套接字读取信息,因为在数据可以被访问之前,读操作将会被阻塞。
此时服务器不能到达,那么应用就会等待长时间,最后由于操作系统的限制而导致超时。
所以,应该确定合理的超时值,调用setSoTimeout方法设置超时值(单位:
毫秒)。
如果你已经为套接字设置了超时值,并且之后的读操作和写操作在没有被完成之前就超时了。
那么操作会抛出一个SocketTimeoutException异常。
捕获异常,做出超时反应。
另外还有一个超时问题是必须解决的。
构造方法:
Socket(Stringhost,intport)
会一直无限制地阻塞下去,直到建立了到达主机的初始连接为止。
可以通过构建一个无连接的套接字,然后再使用一个超时来进行连接的方法解决这个问题。
4.2可中断套接字
当连接到一个套接字时,当前线程将会被阻塞直到建立连接或产生超时为止。
同样地,当通过套接字读取或写数据时,当前线程也会被阻塞直到操作成功或产生超时为止。
在交互式的应用中,也许会考虑为用户提供一个功能,用以取消那些看似不会成功的连接。
但是,当线程因套接字长时间无法响应而发生阻塞时,无法通过调用interrupt来解除阻塞。
为了中断套接字操作,可以使用java.nio.SocketChannel类。
案例:
中断服务器端的线程
中断一个从服务器读取信息的线程。
服务器发送一串随机数到客户端。
如果“忙碌”复选框被选中,那么服务器将假设自己很忙碌而不发送任何消息给客户端。
还有一种情况,当你点击“停止”按钮时,连接将被强行终止。
程序代码:
程序主类SocketTestMain.java
视图窗体类InterruptedSocketFrame.java
随机数多线程类RandomHandler.java
服务端多线程类RandomHandler.java
知识点:
●InetAddress[]getAllByName(Stringhost)
返回一个InetAddress[]对象,数组对象中封装了一个映射网络地址名称对应的多个因特网的IP地址。
(补充)InetAddressgetByName(StringineterName)
将返回一个InetAddress对象,该对象封装对应映射网络地址名称的随机产生的因特网的IP地址。
●StringgetHostAddress()
返回映射网络地址名称的IP地址。
●StringgetHostName()
返回当前映射网络地址名称。
●byte[]getAddress()
返回一个IP地址的byte数组形式。
4.3半关闭
当客户端程序发送一个请求给服务器时,服务器必须能够确定该请求何时结束。
因此,许多网络协议都是面向行的。
其他一些协议则包含一个消息头用以指明请求数据的大小。
否则,想要表示请求数据的结束将比向文件写入数据更加困难。
写一个文件时,只需在数据写入后关闭文件即可。
但是,如果关闭一个套接字,那么将立刻断开与服务器的连接。
使用半关闭的方法就可以解决上述问题。
可以通过关闭一个套接字的输出流来表示发送给服务器的请求数据已经结束,但是必须保留输入流打开用以读取服务器返回的响应信息。
代码演示如何在客户端使用半关闭方法:
4.4因特网地址
因特网地址是指用一串数字表示的主机地址,它由4个字符组成。
例如:
192.168.0.1。
通常,不用过多考虑因特网地址的问题。
但是,如果需要在主机名和因特网地址之间进行转换时,就可以使用InetAddress类。
案例:
地址转换
程序演示如果不在命令行中设置任何参数,那么它将打印出本地主机的因特网地址。
反之,如果在命令行中指定了主机名,那么它将打印出该主机的所有因特网地址。
程序代码:
程序主类InetAddressTest.java
知识点:
●InetAddress[]getAllByName(Stringhost)
返回一个InetAddress[]对象,数组对象中封装了一个映射网络地址名称对应的多个因特网的IP地址。
(补充)InetAddressgetByName(StringineterName)
将返回一个InetAddress对象,该对象封装对应映射网络地址名称的随机产生的因特网的IP地址。
●StringgetHostAddress()
返回映射网络地址名称的IP地址。
●StringgetHostName()
返回当前映射网络地址名称。
●byte[]getAddress()
返回一个IP地址的byte数组形式。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 网络 编程 技术