网络编程
IP地址和端口号
IP地址被分成了A、B、C、D、E五类,每个类别的网络标识和主机标识各有规则。
➢ A类:10.0.0.0~10.255.255.255
➢ B类:172.16.0.0~172.31.255.255
➢ C类:192.168.0.0~192.168.255.255
IP地址用于唯一地标识网络上的一个通信实体,但一个通信实体可以有多个通信程序同时提供网络服务,此时还需要使用端口。端口是一个16位的整数,用于表示数据交给哪个通信程序处理。
端口号可以从0到65535,通常将它分为如下三类。
➢ 公认端口(Well Known Ports):从0到1023,它们紧密绑定(Binding)一些特定的服务。
➢ 注册端口(Registered Ports):从1024到49151,它们松散地绑定一些服务。应用程序通常应该使用这个范围内的端口。
➢ 动态和/或私有端口(Dynamic and/or Private Ports):从49152到65535,这些端口是应用程序使用的动态端口,应用程序一般不会主动使用这些端口。
Java的基本网络支持
Java为网络支持提供了java.net包,该包下的URL和URLConnection等类提供了以编程方式访问Web服务的功能,而URLDecoder和URLEncoder则提供了普通字符串和application/x-www-form-urlencoded MIME字符串相互转换的静态方法。
使用InetAddress
Java提供了InetAddress类来代表IP地址,InetAddress下还有两个子类:Inet4Address、Inet6Address。
InetAddress类没有提供构造器,而是提供了如下两个静态方法来获取InetAddress实例。
➢ getByName(String host):根据主机获取对应的InetAddress对象。
➢ getByAddress(byte[] addr):根据原始IP地址来获取对应的InetAddress对象。
InetAddress还提供了如下三个方法来获取InetAddress实例对应的IP地址和主机名。
➢ String getCanonicalHostName():获取此IP地址的全限定域名。
➢ String getHostAddress():返回该InetAddress实例对应的IP地址字符串(以字符串形式)。
➢ String getHostName():获取此IP地址的主机名。
除此之外,InetAddress类还提供了一个getLocalHost()方法来获取本机IP地址对应的InetAddress实例。InetAddress类还提供了一个isReachable()方法,用于测试是否可以到达该地址。
使用URLDecoder和URLEncoder
URLDecoder和URLEncoder用于完成普通字符串和application/x-www-form-urlencodedMIME字符串之间的相互转换。
➢ URLDecoder类包含一个decode(String s, String enc)静态方法,它可以将看上去是乱码的特殊字符串转换成普通字符串。
➢ URLEncoder类包含一个encode(String s, String enc)静态方法,它可以将普通字符串转换成application/x-www-form-urlencoded MIME字符串。
URL、URLConnection和URLPermission
URL可以由协议名、主机、端口和资源组成,即满足如下格式:
URL类提供了多个构造器用于创建URL对象,一旦获得了URL对象之后,就可以调用如下方法来访问该URL对应的资源。
➢ String getFile():获取该URL的资源名。
➢ String getHost():获取该URL的主机名。
➢ String getPath():获取该URL的路径部分。
➢ int getPort():获取该URL的端口号。
➢ String getProtocol():获取该URL的协议名称。
➢ String getQuery():获取该URL的查询字符串部分。
➢ URLConnection openConnection():返回一个URLConnection对象,它代表了与URL所引用的远程对象的连接。
➢ InputStream openStream():打开与此URL的连接,并返回一个用于读取该URL资源的InputStream。
Java 8新增了一个URLPermission工具类,用于管理HttpURLConnection的权限问题,如果在HttpURLConnection安装了安全管理器,通过该对象打开连接时就需要先获得权限。
使用ServerSocket创建TCP服务器端
Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。
ServerSocket包含一个监听来自客户端连接请求的方法。
➢ Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket;否则该方法将一直处于等待状态,线程也被阻塞。
为了创建ServerSocket对象,ServerSocket类提供了如下几个构造器。
➢ ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该有一个有效的端口整数值,即0~65535。
➢ ServerSocket(int port, int backlog):增加一个用来改变连接队列长度的参数backlog。
➢ ServerSocket(int port, int backlog, InetAddress localAddr):在机器存在多个IP地址的情况下,允许通过localAddr参数来指定将ServerSocket绑定到指定的IP地址。
当ServerSocket使用完毕后,应使用ServerSocket的close()方法来关闭该ServerSocket。在通常情况下,服务器不应该只接收一个客户端请求,而应该不断地接收来自客户端的所有请求,所以Java程序通常会通过循环不断地调用ServerSocket的accept()方法。代码片段如下:
使用Socket进行通信
客户端通常可以使用Socket的构造器来连接到指定服务器,Socket通常可以使用如下两个构造器。
➢ Socket(InetAddress/String remoteAddress, int port):创建连接到指定远程主机、远程端口的Socket,该构造器没有指定本地地址、本地端口,默认使用本地主机的默认IP地址,默认使用系统动态分配的端口。
➢ Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, intlocalPort):创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口,适用于本地主机有多个IP地址的情形。
当客户端、服务器端产生了对应的Socket之后,程序无须再区分服务器端、客户端,而是通过各自的Socket进行通信。Socket提供了如下两个方法来获取输入流和输出流。
➢ InputStream getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。
➢ OutputStream getOutputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据。
UDP协议基础
UDP协议和TCP协议简单对比如下。
➢ TCP协议:可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。
➢ UDP协议:不可靠,差错控制开销较小,传输大小限制在64KB以下,不需要建立连接。