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();
}
}