1.Socket介紹
Socket通信模型。如下圖:
Socket通信實現步驟
- 創建ServerSocket和Socket
- 打開連接到Socket的輸入、輸出流
- 按照協議對Socket進行讀/寫操作
- 關閉輸入輸出流、關閉Socket
2.基於TCP實現Socket編程
TCP協議是面向連接的、可靠的、有序的,以字節流的方式發送數據
基於TCP協議實現網絡通信的類
- 客戶端的Socket類
- 服務器端的ServerSocket類
服務器端:
-
創建ServerSocket對象,綁定監聽端口。
-
通過accept()方法監聽客戶端請求。
-
連接建立後,通過輸入流讀取客戶端發送的請求信息。
-
通過輸出流向客戶端發送響應信息。
-
關閉相關資源。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args){
try {
//1.創建一個服務器端Socket,即ServerSocket,指定綁定的端口,並監聽此端口
ServerSocket serverSocket=new ServerSocket(8888);
//2.調用accept()方法開始監聽,等待客戶端的連接
System.out.println("***服務器即將啓動,等待客戶端的連接***");
Socket socket = serverSocket.accept();
//3.獲取輸入流,並讀取客戶端信息
InputStream is = socket.getInputStream();//字節輸入流
InputStreamReader isr =new InputStreamReader(is);//將字節流轉換爲字符流
BufferedReader br = new BufferedReader(isr);//爲輸入流添加緩衝
String info = null;
while ((info=br.readLine())!=null){
System.out.println("我是服務端,客戶端說:"+info);
}
socket.shutdownInput();
//4.獲取輸出流,響應客戶端的請求
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("歡迎您!");
pw.flush();
//5.關閉資源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
客戶端:
-
創建Socket對象,指明需要連接的服務器的地址和端口號
-
連接建立後,通過輸出流向服務器端發送請求信息。
-
通過輸入流獲取服務器端響應的信息。
-
關閉相關資源。
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) {
try {
//1.創建客戶端Socket,指定服務器地址和端口
Socket socket=new Socket("localhost", 8888);
//2.獲取輸出流,向服務器端發送信息
OutputStream os=socket.getOutputStream();//字節輸出流
PrintWriter pw=new PrintWriter(os);//將輸出流包裝爲打印流
pw.write("用戶名:alice;密碼:789");
pw.flush();
socket.shutdownOutput();//關閉輸出流
//3.獲取輸入流,並讀取服務器端的響應信息
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String info=null;
while((info=br.readLine())!=null){
System.out.println("我是客戶端,服務器說:"+info);
}
//4.關閉資源
br.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
運行時,先運行服務端,再運行客戶端代碼。
運行結果如下:
服務端:
***服務器即將啓動,等待客戶端的連接***
我是服務端,客戶端說:用戶名:alice;密碼:789
客戶端:
我是客戶端,服務器說:歡迎您!
3.基於UDP實現Socket編程
UDP協議是無連接、不可靠的、無序的
UDP協議以數據報作爲數據傳輸的載體
進行數據傳輸時,首先要將傳輸的數據定義成數據報(Datagram),在數據報中指明要到達的Socket(主機地址和端口號),然後再將數據報發送出去。
- DatagramPacket:表示數據報包
- DatagramSocket:進行端到端通信的類
服務端:
UDP服務器端實現步驟
- 創建DatagramSocket,指定端口號。
- 創建DatagramPacket數據報。
- 使用DatagramSocket的receive(packet)方法接收客戶端發送的數據信息。
- 讀取信息。
public class UDPServer {
public static void main(String[] args) throws IOException {
/*
* 接收客戶端發送的數據
*/
//1.創建服務器端DatagramSocket,指定端口
DatagramSocket socket=new DatagramSocket(8800);
//2.創建數據報,用於接收客戶端發送的數據
byte[] data =new byte[1024];//創建字節數組,指定接收的數據包的大小
DatagramPacket packet=new DatagramPacket(data, data.length);
//3.接收客戶端發送的數據
System.out.println("****服務器端已經啓動,等待客戶端發送數據");
socket.receive(packet);//此方法在接收到數據報之前會一直阻塞
//4.讀取數據
String info=new String(data, 0, packet.getLength());
System.out.println("我是服務器,客戶端說:"+info);
/*
* 向客戶端響應數據
*/
//1.定義客戶端的地址、端口號、數據
InetAddress address=packet.getAddress();
int port=packet.getPort();
byte[] data2="歡迎您!".getBytes();
//2.創建數據報,包含響應的數據信息
DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);
//3.響應客戶端
socket.send(packet2);
//4.關閉資源
socket.close();
}
}
客戶端:
UDP客戶端實現步驟
- 定義發送信息
- 創建DatagramPacket數據報,包含將要發送的信息。
- 創建DatagramSocket對象。
- 使用DatagramSocket的send()方法發送數據。
public class UDPClient {
public static void main(String[] args) throws IOException {
/*
* 向服務器端發送數據
*/
//1.定義服務器的地址、端口號、數據
InetAddress address=InetAddress.getByName("localhost");
int port=8800;
byte[] data="用戶名:admin;密碼:123".getBytes();
//2.創建數據報,包含發送的數據信息
DatagramPacket packet=new DatagramPacket(data, data.length, address, port);
//3.創建DatagramSocket對象
DatagramSocket socket=new DatagramSocket();
//4.向服務器端發送數據報
socket.send(packet);
/*
* 接收服務器端響應的數據
*/
//1.創建數據報,用於接收服務器端響應的數據
byte[] data2=new byte[1024];
DatagramPacket packet2=new DatagramPacket(data2, data2.length);
//2.接收服務器響應的數據
socket.receive(packet2);
//3.讀取數據
String reply=new String(data2, 0, packet2.getLength());
System.out.println("我是客戶端,服務器說:"+reply);
//4.關閉資源
socket.close();
}
}
運行結果如下:
服務端:
****服務器端已經啓動,等待客戶端發送數據
我是服務器,客戶端說:用戶名:admin;密碼:123
客戶端:
我是客戶端,服務器說:歡迎您!