1. UDP
UDP是用户数据包协议。Java中实现UDP协议的类是DatagramPacket和DatagramSocket. DatagramPacket类将数据字节填充到UDP包中,成为“数据报”。DatagramSocket类将数据报发送出去。
MulticastSocket类是DatagramSocket类的子类,用于广播和组播的客户端。
1.1 单播
单台主机与单台主机之间的通信
client.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; public class ClientTest { private static final int MAXRECEIVED = 255; public static void main(String[] args) throws IOException { byte[] msg = new String("connect test successfully!!!").getBytes(); DatagramSocket client = new DatagramSocket(); InetAddress inetAddr = InetAddress.getLocalHost(); SocketAddress socketAddr = new InetSocketAddress(inetAddr, 8888); DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, socketAddr); client.send(sendPacket); client.close(); } }
server.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.Arrays; public class ServerTest { private static final int MAXREV = 255; public static void main(String[] args) throws IOException { DatagramSocket server = new DatagramSocket(8888); DatagramPacket recvPacket = new DatagramPacket(new byte[MAXREV], MAXREV); while (true) { server.receive(recvPacket); byte[] receiveMsg = Arrays.copyOfRange(recvPacket.getData(), recvPacket.getOffset(), recvPacket.getOffset() + recvPacket.getLength()); System.out.println("Handing at client " + recvPacket.getAddress().getHostName() + " ip " + recvPacket.getAddress().getHostAddress()); System.out.println("Server Receive Data:" + new String(receiveMsg)); server.send(recvPacket); } } }
1.2 广播
单台主机与网络中所有主机的通信,代码与单播类似,只要使用广播地址255.255.255.255即可,再有就是因为会有多个客户端同时连服务端,所以客户端要用MulticastSocket
client.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class BroadcastSender { public static void main(String[] args) throws IOException { byte[] msg = new String("connection successfully!!!").getBytes(); /* * 在Java UDP中单播与广播的代码是相同的,要实现具有广播功能的程序只需要使用广播地址即可, 例如:这里使用了本地的广播地址 */ InetAddress inetAddr = InetAddress.getByName("255.255.255.255"); MulticastSocket client = new MulticastSocket(); DatagramPacket sendPack = new DatagramPacket(msg, msg.length, inetAddr, 8888); client.send(sendPack); System.out.println("Client send msg complete"); client.close(); } }
server.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.Arrays; public class BroadcastReceive { public static void main(String[] args) throws IOException { DatagramPacket receive = new DatagramPacket(new byte[1024], 1024); DatagramSocket server = new DatagramSocket(8888); System.out.println("---------------------------------"); System.out.println("Server current start......"); System.out.println("---------------------------------"); while (true) { server.receive(receive); byte[] recvByte = Arrays.copyOfRange(receive.getData(), 0, receive.getLength()); System.out.println("Server receive msg:" + new String(recvByte)); } } }
1.3 组播
只对加入组的主机广播。组播IP地址为224.0.0.0~239.255.255.255.
client.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; //客户端 public class MulticastSender { public static void main(String[] args) throws IOException { int port = 8888; byte[] msg = "Connection successfully!!!".getBytes(); InetAddress inetRemoteAddr = InetAddress.getByName("224.0.0.5"); /* * Java UDP组播应用程序主要通过MulticastSocket实例进行通信,它是DatagramSocket的是一个子类, * 其中包含了一些额外的可以控制多播的属性. * * 注意: * * 多播数据报包实际上可以通过DatagramSocket发送,只需要简单地指定一个多播地址。 * 我们这里使用MulticastSocket,是因为它具有DatagramSocket没有的能力 */ MulticastSocket client = new MulticastSocket(); DatagramPacket sendPack = new DatagramPacket(msg, msg.length, inetRemoteAddr, port); client.send(sendPack); System.out.println("Client send msg complete"); client.close(); } }
server.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.util.Arrays; //服务端 public class MulticastReceive { public static void main(String[] args) throws IOException { InetAddress inetRemoteAddr = InetAddress.getByName("224.0.0.5"); DatagramPacket recvPack = new DatagramPacket(new byte[1024], 1024); MulticastSocket server = new MulticastSocket(8888); /* * 如果是发送数据报包,可以不加入多播组; 如果是接收数据报包,必须加入多播组; 这里是接收数据报包,所以必须加入多播组; */ server.joinGroup(inetRemoteAddr); System.out.println("---------------------------------"); System.out.println("Server current start......"); System.out.println("---------------------------------"); while (true) { server.receive(recvPack); byte[] recvByte = Arrays.copyOfRange(recvPack.getData(), 0, recvPack.getLength()); System.out.println("Server receive msg:" + new String(recvByte)); } } }
2. TCP
TCP通过三次握手建立连接,通过字节流发送数据。Java中基于TCP协议实现的网络通信的类是:
客户端的Socket类
服务器端的ServerSocket类
服务端用ServerSocket类建立一个socket,等待客户端连接。服务端与客户端建立连接后,用Socket类以InputStream/OutputStream的方式发送/接收数据。
client.java
package client; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.MulticastSocket; import java.net.Socket; import java.util.Arrays; public class RunClientThread extends Thread { public static final int DATA_BUFFER_SIZE = 256; public RunClientThread() { Thread th = new Thread(this); th.start(); } public void run() { // 从TCP server接收初始信息 String host = "localhost"; int port = 1122; try { Socket socket = new Socket(host,port); InputStream is = socket.getInputStream(); BufferedReader bf = new BufferedReader(new InputStreamReader(is)); String line; while((line = bf.readLine())!=null) { System.out.println(line); } bf.close(); is.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
server.java
package server; import java.io.BufferedReader; import java.io.FileReader; import java.io.OutputStream; import java.net.Socket; public class SingleServerThread extends Thread{ Socket socket; OutputStream os; public SingleServerThread(Socket soc) { // 构造函数 socket = soc; } public void run() { // 线程主体 try { os = socket.getOutputStream(); String line; BufferedReader is = new BufferedReader(new FileReader("events.properties")); while ((line=is.readLine())!=null) { // 文件不到末尾 line = line + "\n"; // 加换行符 byte[] msg = line.getBytes(); // 转换成字节流 os.write(msg); } is.close(); // 关闭文件 socket.close(); // 关闭Socket } catch (Exception e) { System.out.println("Error:" + e); // 出错,打印出错信息 } } }
Main.java
package server; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class RunServer { /** * @param args */ public static void main(String[] args) throws IOException{ // 创建TCP socket ServerSocket ss = new ServerSocket(1122); System.out.println("TCP server begins to work..."); while (true) { Socket soc = ss.accept(); System.out.println("TCP user accepted!"); new SingleServerThread(soc).start(); // 每建立一个TCP连接,就创建一个TCP server线程 } } }