Java 网络编程
网络编程三要素
- IP 地址:设备在网络中的地址,是唯一的标识。
- 端口号:应用程序在设备中的唯一标识。取值范围 0 ~ 65535,一般 0 ~1023 之间的端口用于固定网络服务或系统应用,一般自己使用 1024 以上的端口。一个端口只能被一个应用程序使用。
- 协议:数据在网络中传输的规则,常见协议有 UDP 和 TCP。
InetAddress 类
该类表示 IP 地址。
- getByName:根据主机名获取 InetAddress 对象。
- getHostName:获取主机名。
- getHostAddress:以字符串形式获取 IP 地址。
例:
public static void main(String[] args) throws UnknownHostException {
InetAddress inetAddress = InetAddress.getByName("localhost");
System.out.println("主机名为:" + inetAddress.getHostName());
System.out.println("IP地址为:" + inetAddress.getHostAddress());
}
UDP 通信
UDP 的三种通信方式:
单播
发送端代码:
public class UDPClient {
public static void main(String[] args) throws Exception {
// 创建发送端 socket 对象
DatagramSocket socket = new DatagramSocket();
// 打包要发送的数据
byte[] bytes = "HELLO UDP".getBytes();
InetAddress address = InetAddress.getByName("localhost");
int port = 8080;
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
// 发送数据
socket.send(packet);
// 释放资源
socket.close();
}
}
接收端代码:
public class UDPServer {
public static void main(String[] args) throws Exception{
// 创建接收端 socket 对象,表示从 8080 端口接收数据
DatagramSocket socket = new DatagramSocket(8080);
// 准备接收数据
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
// 接收数据
socket.receive(packet);
// 获取数据
int length = packet.getLength();
System.out.println(new String(bytes, 0, length));
// 释放资源
socket.close();
}
}
如果接收端没有接收到数据,会在 socket.receive(packet);
处阻塞。
组播
组播地址 224.0.0.0 ~ 239.255.255.255,其中 224.0.0.0 ~224.0.0.255 不可用。
发送端代码:
public class UDPClient {
public static void main(String[] args) throws Exception {
// 创建发送端 socket 对象
DatagramSocket socket = new DatagramSocket();
// 打包要发送的数据
byte[] bytes = "HELLO UDP".getBytes();
// 224.0.1.0 表示组播地址
InetAddress address = InetAddress.getByName("224.0.1.0");
int port = 8080;
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
// 发送数据
socket.send(packet);
// 释放资源
socket.close();
}
}
接收端代码:
public class UDPServer {
public static void main(String[] args) throws Exception{
// 创建接收端 socket 对象(注意使用 MulticastSocket),从 8080 端口接收数据,
MulticastSocket socket = new MulticastSocket(8080);
// 准备接收数据
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
// 把当前计算机绑定到组播地址
socket.joinGroup(InetAddress.getByName("224.0.1.0"));
// 接收数据
socket.receive(packet);
// 获取数据
int length = packet.getLength();
System.out.println(new String(bytes, 0, length));
// 释放资源
socket.close();
}
}
广播
发送端代码:
public class UDPClient {
public static void main(String[] args) throws Exception {
// 创建发送端 socket 对象
DatagramSocket socket = new DatagramSocket();
// 打包要发送的数据
byte[] bytes = "HELLO UDP".getBytes();
InetAddress address = InetAddress.getByName("255.255.255.255");
int port = 8080;
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
// 发送数据
socket.send(packet);
// 释放资源
socket.close();
}
}
接收端代码:
public class UDPServer {
public static void main(String[] args) throws Exception{
// 创建接收端 socket 对象,表示从 8080 端口接收数据
DatagramSocket socket = new DatagramSocket(8080);
// 准备接收数据
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
// 接收数据
socket.receive(packet);
// 获取数据
int length = packet.getLength();
System.out.println(new String(bytes, 0, length));
// 释放资源
socket.close();
}
}
TCP 通信
TCP 在通信两端各建立一个 Socket 对象,发送端是 Socket,接收端是 ServerSocket,通信之前要保证连接已经建立。
发送端代码:
public class TCPClient {
public static void main(String[] args) throws Exception{
// 创建发送端 socket
Socket socket = new Socket("localhost", 8080);
// 获取字节输出流
OutputStream os = socket.getOutputStream();
// 写数据
os.write("hello tcp".getBytes());
// 释放资源
os.close();
socket.close();
}
}
接收端代码:
public class TCPServer {
public static void main(String[] args) throws Exception{
// 创建接收端 socket
ServerSocket serverSocket = new ServerSocket(8080);
// 获取客户端连接 socket,获取不到将阻塞
Socket socket = serverSocket.accept();
// 获取字节输入流
InputStream is = socket.getInputStream();
// 读数据,如果发送端没有释放资源会阻塞
int b;
while ((b = is.read()) != -1){
System.out.print((char)b);
}
// 释放资源
is.close();
socket.close();
serverSocket.close();
}
}
TCP 练习1:双方互相发送数据
客户端:发送数据,接收服务器反馈。
public class TCPClient {
public static void main(String[] args) throws Exception{
// 创建发送端 socket
Socket socket = new Socket("localhost", 8080);
// 获取字节输出流并发送数据
OutputStream os = socket.getOutputStream();
os.write("hello tcp".getBytes());
// 写一个结束标记,关闭输出流
socket.shutdownOutput();
// 获取字符输入流并读取反馈
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = br.readLine()) != null){
System.out.print(line);
}
// 释放资源
br.close();
os.close();
socket.close();
}
}
服务器:接收数据,给出反馈。
public class TCPServer {
public static void main(String[] args) throws Exception{
// 创建接收端 socket
ServerSocket serverSocket = new ServerSocket(8080);
// 获取客户端连接 socket,获取不到将阻塞
Socket socket = serverSocket.accept();
// 获取字节输入流并读取数据
InputStream is = socket.getInputStream();
int b;
while ((b = is.read()) != -1){
System.out.print((char)b);
}
// 获取字符输出流并反馈
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("已收到");
// 释放资源
bw.close();
is.close();
socket.close();
serverSocket.close();
}
}
TCP 练习2:文件上传
客户端:将本地文件上传到服务器,接收服务器反馈。
public class FileUpload {
public static void main(String[] args) throws Exception{
// 创建客户端 socket
Socket socket = new Socket("localhost", 8080);
// 要上传的文件
File file = new File("C:\\a.jpg");
// 本地字节输入流,读取文件
InputStream is = new FileInputStream(file);
// 网络字节输出流,上传文件
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[1024];
int read;
while ((read = is.read(bytes)) != -1){
os.write(bytes, 0, read);
}
socket.shutdownOutput();
// 接收服务端提示
is = socket.getInputStream();
while ((read = is.read()) != -1){
System.out.print((char)read);
}
// 释放资源
is.close();
os.close();
socket.close();
}
}
服务器:接收客户端上传的文件,接收成功后给出反馈。
public class FileReceive {
public static void main(String[] args) throws Exception{
// 创建服务端 socket
ServerSocket serverSocket = new ServerSocket(8080);
// 接收客户端 socket
Socket socket = serverSocket.accept();
// 网络字节输入流,读取文件
InputStream is = socket.getInputStream();
// 本地字节输出流,保存到对应文件夹
OutputStream os = new FileOutputStream(new File("C:\\b.jpg"));
byte[] bytes = new byte[1024];
int read;
while ((read = is.read(bytes)) != -1){
os.write(bytes, 0, read);
}
// 提示客户端上传成功
os = socket.getOutputStream();
os.write("file upload successfully".getBytes());
// 释放资源
os.close();
is.close();
socket.close();
serverSocket.close();
}
}