Java网络编程
Java的基本网络支持
使用InetAddress
Java提供了InteAddress类来代表IP地址,没有提供构造器,而是提供了如下两个静态方法来获取InetAddress实例。
- getByName(String host)
- getByAddress(byte[] addr)
- getLocalHost,获取本机IP地址对应的实例。
获取信息:
- String getCanonicalHostName()
- String getHostAddress()
- String getHostName()
- boolean isReachable()
1 | public class InetAddressTest |
使用URLDecoder和URLEncoder
普通字符串和application/x-www-form-urlencode MIME字符串的转换。
1 | public class URLDecoderTest |
URL,URLConnection和URLPermission
URL对象代表统一资源定位器,是指向互联网资源指针。资源可以是简单的文件,也可是更加复杂的引用。通常URL有协议名、主机、端口和资源组成。protocol:://host:port/resourceName
- String getFile()
- String getHost()
- String getPath()
- int getPort()
- String getProtocol()
- String getQuery()
- URLConnection openConnection()
- InputStream openStream()
一个简单的多线程下载工具类:
1 | public class DownUtil |
1 | public class MultiThreadDown |
上面的程序还用到URLConnection和HttpURLConnection对象,其中前者表示应用程序和URL之间的通信连接,后者表示与URL之间的HTTP连接。程序可以功过URLConnection实例向该URL发送请求,读取URL引用的资源。
上面是直接获取输入流然后写到本地,连接操作都隐藏在openStream中了。
通常创建一个和URL的连接,并发送请求、读取此URL的资源需要如下几个步骤:
- 调用URL对象的openConnection()方法来创建URLConnection对象。
- 设置URLConnection的参数和普通请求属性
- 如果只是发送GET方式请求,则使用connect()方法建立和远程资源之间的实际连接即可;如果要发送POST方式的请求,则需要获取URLConnection实例对应的输出流来发送请求参数。
- 远程资源变为可用,程序可以访问远程资源的头字段或通过输入流读取远程资源的数据。在建立和远程资源的实际连接之前。程序可以通过如下方法来设置字段的值:
- setAllowUserInteraction()
- setDoInput()
- setDoOutput()
- setRequestProperty(String key, String value)
远程资源可用后:
- Object getConnect()
- String getHeaderField(String name)
- getInputStream()
- getOutputStream
1 | ublic class GetPostTest |
基于TCP协议的网络编程
TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信的两端形成网络虚拟链路。一旦建立了虚拟链路,两端的程序就可以通过虚拟链路通信。Java使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
TCP协议基础
TCP协议负责信息包的按顺序传送,接收端收到后再将其正确还原。TCP通过重发以及确认机制保证准确传送,同时能够自适应网络的拥塞情况。
使用ServerSoket创建TCP服务器端
ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,则一直处于等待状态。
- Socket accept(): 如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket。
构造器:
- ServerSocket(int port)
- ServerSocket(int prot, int backlog)
- ServerSocket(int port, int backlog, InetAddress localAddr)
使用Socket进行通信
客户端可以使用Socket构造器来连接到指定的服务器:
- Socket(InetAdress/String remoteAddress, int port)
Socket(InetAdress/String remoteAddress, int port, InetAddress localAddr, int localPort)
InputStream getInputStream()
- OutputStream getOutputStream()
1 | public class Server |
1 | public class Client |
可以设定超时时长:setSoTimeout(10000)
1 | try { |
另一种建立连接的方式:
1 | Socket s = new Socket(); |
加入多线程
1 | public class MyServer |
1 | // 负责处理每个线程通信的线程类 |
1 | public class MyClient |
1 | public class ClientThread implements Runnable |
半关闭的Socket
Socket提供半关闭方法,用来只关闭输入流或输出流,用以表示输出数据已经完成。
- shutdownInput()
- shutdownOutput()
- isInputShutdown()
- isOutputShutdown()
1 | public class Server |
1 | public class Client |
使用NIO实现非阻塞Socket通信
使用Java 7的AIO实现非阻塞通信
基于UDP协议的网络编程
UDP协议是一种不可靠的网络协议,它在通信实例的两段各建立一个Socket,但这两个Socket之间并没有虚拟链路,只是发送接受数据报的对象。Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagamSocket发送、接收的数据报。
UDP协议基础
同前面TCP一样,UDP协议直接建立于IP协议之上。IP实际上是网络层协议,UDP和TCP为传输层协议。
UDP面向非连接,通信效率高,当可靠性不如TCP协议,传输大小限制64KB一下,不保证正确顺序。
使用DatagramSocket发送、接收数据
Java使用DatagramSocket对象作为基于UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,唯一作用是接收和发送数据报。Java使用DatagramPacket来代表数据报。
- DatagramSocket()
- DatagramSocket(int port)
DatagramSocket(int port, InetAddress laddr)
receive(DatagramPacket p)
- send(DatagramPacket p)
DatagramSocket并不知道把数据发送到哪里,而是有DatagramPacket自身决定数据报的目的地。
DatagramPacket的构造器:
- DatagramPacket(byte[] buf, int length) 接收数据
- DatagramPacket(byte[] buf, int offset, int length)
- DatagramPacket(byte[] buf, int length, InetAddress addr, int port) 发送数据
- DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
1 | DatagramPacket packet = new DatagramPacket(buf, 256) |
- InetAddress getAddress()
- int getPort()
- SocketAddress getSocketAddress()
1 | public class UdpServer |
1 | public class UdpClient |
使用MulticastSocket实现多点广播
DatagramSocket只允许数据报发送给制定的目标地址,而MulticastSocket可以将数据报以广播形式发送到多个客户端。
若要使用多点广播,则需要让一个数据报标有一组目标主机地址,当数据报发出后,整个组的所有主机都能收到该数据报。IP多点广播实现了将单一信息发送到多个接受者的广播,其主要思想是设置一批特殊的网络地址作为多点广播地址,每个多点广播地址可以看为一个组,当需要发送,接收广播信息时,加入该组就可。当不需要时,就离开该组。
- public MulticastSocket()
- public MulticastSocket(int protNum)
public MulticastSocket(SocketAddress binaddr)
joinGroup(InetAddress multicastAddr): 将MulticastSocket加入一个组
leaveGroup(InetAddress multicastAddr): 将MulticastSocket离开一个组
setTimeToLive(int ttl),设置数据报最多可以跨过多少个网络。
1 | public class MulticastSocketTest implements Runnable |