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线程
}
}
}