Java – 网络编程
简介
本篇文章讲解如何使用Java进行网络通讯编程,包含UDP与TCP的数据传输,发送与接收。
InetAddress 网络地址
InetAddress 是Java中用于表达 IP 地址的类,它可以通过【计算机名】或【IP】地址来获取到设备的IP
创建 InetAddress 网络地址
通过静态方法获得InetAddress 对象
// 以 IP 地址创建 InetAddress 对象
InetAddress ip = Inet4Address.getByName("127.0.0.1");
// 以 计算机名 创建 InetAddress 对象
InetAddress name = Inet4Address.getByName("TZMing-PC");
// 获取该计算机名的 IP 地址
System.out.println(name.getHostAddress());
// 获取该IP地址对应的计算机名(有可能失败,也会输出IP)
System.out.println(ip.getHostName());
UDP网络编程
UDP 是一种无连接状态的网络传输层,它发送数据时不会考虑对方计算机是否已建立连接状态,不管对方是否成功接收,都不会考虑。是一种有损数据传输协议
UDP 发送数据
UDP发送数据需要提供两个类,分别是负责创建UDP数据发送对象类【DatagramSocket】,和负责打包数据对象类【DatagramPacket】
DatagramSocket 提供三种构造方法,
// 无参构造:发送数据将使用随机端口号发出
new DatagramSocket()
// 有参构造:发送数据将使用指定端口号发出
new DatagramSocket(int port)
// 有参构造:发送数据将使用指定端口号和指定ip发出
new DatagramSocket(int port, InetAddress ip)
DatagramPacket 提供了6种构造方法
DatagramPacket(@NotNull byte[] buf, int offset, int length)
DatagramPacket(@NotNull byte[] buf, int length)
DatagramPacket(@NotNull byte[] buf,int offset, int length, InetAddress address, int port)
DatagramPacket(@NotNull byte[] buf, int offset, int length, SocketAddress address)
DatagramPacket(@NotNull byte[] buf, int length, InetAddress address, int port)
DatagramPacket(@NotNull byte[] buf, int length, SocketAddress address)
buf 是要发送的数据
offset 是指定发送数据中的偏移值
length 要发送的字节长度
address 要发送到的ip
port 要发送到的端口
Demo
// 创建一个ip对象
InetAddress ip = Inet4Address.getByName("127.0.0.1");
// 创建一个UDP发送对象
DatagramSocket ds = new DatagramSocket();
// 创建要发送的数据
String str = "你好";
byte[] bytes = str.getBytes();
// 创建数据包对象
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, ip, port);
// 发送数据
ds.send(dp);
// 关闭连接
ds.close();
UDP 接收数据
UDP 接收数据同样需要使用数据发送对象类【DatagramSocket】,和负责打包数据对象类【DatagramPacket】。
通过【DatagramSocket】来建立UDP连接,再通过【DatagramPacket】来存放接收的数据包
// 创建一个UDP连接对象
DatagramSocket ds = new DatagramSocket(10086);
// 创建一个byte数组,用于存放接收的数据
byte[] data = new byte[1024];
// 创建一个数据包对象,用于接收传过来的数据
DatagramPacket dp = new DatagramPacket(data,data.length);
// 等待接收数据,在这个过程中,程序是阻塞的
ds.receive(dp);
// 接收完后可以取得数据包中的数据,但数据包含空字节数据
byte[] recData = dp.getData();
// 获取接收数据的精确长度
int dataLength = dp.getLength();
// 在 1024 字节中取出有效的数据
String str = new String(recData, 0, dataLength);
System.out.println(str);
// 获取发送者的ip地址信息
InetAddress revIP = dp.getAddress();
// 获取发送者的端口信息
int port = dp.getPort();
组播
组播是指把一部分电脑作为一个组,发送者只需要发送到组播地址,所有该组的设备都能收到消息
组播地址:224.0.0.0~239.255.255.255
其中: 224.0.0.0~224.0.0.255 为预留的组播地址
public static void main(String[] args) throws IOException {
// 创建一个ip对象,并把数据发送到组播地址中
InetAddress ip = Inet4Address.getByName("224.0.0.1");
// 创建一个UDP发送对象
MulticastSocket ms = new MulticastSocket();
// 创建要发送的数据
String str = "你好";
byte[] bytes = str.getBytes();
// 创建数据包对象
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, ip, 10086);
// 发送数据
ms.send(dp);
// 关闭连接
ms.close();
}
接收时,把本机加入到组播中即可
public static void rec() throws IOException {
// 设置本机接收ip为224.0.0.1组播地址
InetAddress ip = Inet4Address.getByName("224.0.0.1");
// 创建一个UDP连接对象
MulticastSocket ms = new MulticastSocket(10086);
// 把本机加入到组播组中
ms.joinGroup(ip);
// 创建一个byte数组,用于存放接收的数据
byte[] data = new byte[1024];
// 创建一个数据包对象,用于接收传过来的数据
DatagramPacket dp = new DatagramPacket(data,data.length);
// 等待接收数据,在这个过程中,程序是阻塞的
ms.receive(dp);
// 接收完后可以取得数据包中的数据,但数据包含空字节数据
byte[] recData = dp.getData();
// 获取接收数据的精确长度
int dataLength = dp.getLength();
// 在 1024 字节中取出有效的数据
String str = new String(recData, 0, dataLength);
System.out.println(str);
// 获取发送者的ip地址信息
InetAddress revIP = dp.getAddress();
// 获取发送者的端口信息
int port = dp.getPort();
}
广播
广播是指发送者发送到广播地址,所有的设备都会收到同样的消息
广播地址为:255.255.255.255
public static void main(String[] args) throws IOException {
// 创建一个ip对象,并把数据发送到组播地址中
InetAddress ip = Inet4Address.getByName("255.255.255.255");
// 创建一个UDP发送对象
DatagramSocket ds = new DatagramSocket();
// 创建要发送的数据
String str = "你好";
byte[] bytes = str.getBytes();
// 创建数据包对象
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, ip, 10086);
// 发送数据
ds.send(dp);
// 关闭连接
ds.close();
}
TCP 网络编程
对于tcp网络编程而言,网络在发送之前需要对客户端和服务器建立连接后,才可以发送数据
TCP客户端发送数据
public static void main(String[] args) throws IOException {
// 1. 创建socket 对象,提供ip和端口构造参数
Socket socket = new Socket("127.0.0.1",1234);
// 2. 对发送者而言,发送则是输出流,所以取出输出流
OutputStream outputStream = socket.getOutputStream();
// 3. 输出流写出数据
outputStream.write("aaa".getBytes());
// 4. 关闭流
outputStream.close();
socket.close();
}
TCP服务器接收数据
public static void main(String[] args) throws IOException {
// 1. 创建 ServerSocket 对象,用于监听端口
ServerSocket ss = new ServerSocket(1234);
// 2. 开始监听端口中的数据,在未接收到数据之前都是阻塞状态
Socket data = ss.accept();
// 3. 接收到数据时,对于服务器而言是输入流,取出输入流
InputStream is = data.getInputStream();
// 4. 对接收到的数据进行读取
int b;
while ((b = is.read()) != -1) {
System.out.println((char) b);
}
// 5. 关闭流
is.close();
ss.close();
}
注意:使用 InputStream 字节流接收数据,会因编码问题对中文产生乱码,主要原因是Java会默认使用ASCII码进行解码,可以使用字符流或使用缓冲流进行数据读取。
public static void main(String[] args) throws IOException {
// 1. 创建 ServerSocket 对象,用于监听端口
ServerSocket ss = new ServerSocket(1234);
// 2. 开始监听端口中的数据,在未接收到数据之前都是阻塞状态
Socket data = ss.accept();
// 3. 接收到数据时,对于服务器而言是输入流,取出输入流
InputStream is = data.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
// 4. 对接收到的数据进行读取
int b;
while ((b = br.read()) != -1) {
System.out.println((char) b);
}
// 5. 关闭流
is.close();
ss.close();
}
共有 0 条评论