第35 章 : 網絡程式設計
152 網絡程式設計簡介
網絡程式設計: 多台主機之間的資料通信
通信協定:IP、TCP(可靠資料連接配接)、UDP(不可靠資料連接配接)
網絡程式模型:
C/S Client/Server 用戶端/服務端 安全性高 開發成本高
B/S Browser/Server 浏覽器/伺服器 安全性較低 開發成本低
目前以B/S 結構為主
153 Echo程式模型
ServerSocket與Socket
ServerSocket 設定伺服器監聽端口
Socket 設定要連接配接伺服器的ip和端口
實作一個用戶端與伺服器端通信 Echo服務
Server.java
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
// 設定伺服器監聽端口
ServerSocket server = new ServerSocket(8080);
System.out.println("服務啟動。。。");
// 接收用戶端連接配接
Socket client = server.accept();
// 接收用戶端消息
Scanner scanner = new Scanner(client.getInputStream());
scanner.useDelimiter("\n");
// 發送給用戶端資料
PrintWriter out = new PrintWriter(client.getOutputStream());
// 結束标志
boolean flag = true;
while (flag) {
if (scanner.hasNext()) {
// 讀取用戶端資料
String message = scanner.next();
System.out.println("收到: " + message);
// 結束标志
if ("bye".equalsIgnoreCase(message)) {
flag = false;
}
// 發送資料給用戶端
out.println("[echo] " + message);
out.flush();
}
}
// 關閉
out.close();
scanner.close();
client.close();
server.close();
}
}
Client.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private final static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
// 連接配接伺服器
Socket client = new Socket("localhost", 8080);
// 接收伺服器資訊
Scanner scanner = new Scanner(client.getInputStream());
scanner.useDelimiter("\n");
// 向伺服器發送資訊
PrintWriter out = new PrintWriter(client.getOutputStream());
// 結束标志
boolean flag = true;
while (flag) {
// 讀取控制台輸入,發送給伺服器
String message = getInput("請輸入:");
System.out.println("發送:" + message);
out.println(message);
out.flush();
// 接收服務端傳回的資料
if (scanner.hasNext()) {
System.out.println("傳回:" + scanner.next());
}
// 結束标志
if ("bye".equalsIgnoreCase(message)) {
flag = false;
}
}
// 關閉操作
out.close();
scanner.close();
client.close();
}
// 接收控制台輸入
public static String getInput(String prompt) throws IOException {
System.out.println(prompt);
return reader.readLine();
}
}
154 BIO處理模型
多線程接收多個用戶端連接配接
隻用修改服務端代碼
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static class ClientThread implements Runnable {
private Socket client = null;
private Scanner scanner = null;
private PrintWriter out = null;
private boolean flag = true; // 結束标志
ClientThread(Socket client) throws IOException {
this.client = client;
// 接收用戶端消息
this.scanner = new Scanner(client.getInputStream());
this.scanner.useDelimiter("\n");
// 發送給用戶端資料
this.out = new PrintWriter(client.getOutputStream());
}
@Override
public void run() {
while (this.flag) {
if (this.scanner.hasNext()) {
// 讀取用戶端資料
String message = this.scanner.next();
System.out.println("收到: " + Thread.currentThread() + message);
// 結束标志
if ("bye".equalsIgnoreCase(message)) {
this.flag = false;
}
// 發送資料給用戶端
this.out.println("[echo] " + message);
this.out.flush();
}
}
this.out.close();
this.scanner.close();
try {
this.client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
// 設定伺服器監聽端口
ServerSocket server = new ServerSocket(8080);
System.out.println("服務啟動。。。");
while (true) {
// 接收用戶端連接配接
Socket client = server.accept();
new Thread(new ClientThread(client)).start();
}
// 關閉
// server.close();
}
}
155 UDP程式
UDP 基于資料報實作
TCP要保證可靠連接配接,需要的伺服器資源就多
不管用戶端是否接收到
Receiver.java
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Receiver {
public static void main(String[] args) throws IOException {
DatagramSocket receiver = new DatagramSocket(9000);
byte[] data = new byte[2014];
DatagramPacket packet = new DatagramPacket(data, data.length);
// 等待接收資料
receiver.receive(packet);
System.out.println(new String(data, 0, packet.getLength()));
// 關閉
receiver.close();
}
}
Sender.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Sender {
public static void main(String[] args) throws Exception {
DatagramSocket sender = new DatagramSocket(9001);
// 發送資料
String message = "Hello world";
DatagramPacket packet = new DatagramPacket(message.getBytes(), 0, message.length(), InetAddress.getByName("localhost"), 9000);
sender.send(packet);
// 關閉
sender.close();
}
}