JAVA基於TCP和UDP的Socket通信

——Http屬於應用層——

——TCP/IP屬於傳輸層——

TCP協議(傳輸控制協議)是面向連接、可靠的,以字節流方式發送數據

可以使用Socket進行網絡通信,需要雙方通信設備的IP和端口號

常見端口號http80 ftp21 telnet23

——UDP/IP屬於傳輸層——

UDP協議(用戶數據報協議)是無連接、不可靠、無序的,以數據報(Datagram)方式發送數據

相關操作類:DatagramPacket數據報包,DatagramSocket進行端到端通信的類

——Socket就是網絡上運行的兩個程序之間的雙向通信鏈路的終結點——

基於TCP協議實現網絡通信的類:客戶端的Socket和服務器的ServerSocket

 

——以下Socket是基於TCP/IP協議的——

Socket通信實現的步驟:

1、創建ServerSocketSocket

2、打開連接到Socket的輸入輸出流

3、按照協議對Socket進行讀寫操作

4、關閉輸入輸出流和Socket

服務器端:

1、創建ServerSocket,綁定監聽端口

2、通過accept方法監聽客戶端請求

3、連接建立後,通過輸入流讀取客戶端發送的請求信息

4、通過輸出流向客戶端發送響應的信息

5、關閉相關資源

客戶端:

1、創建Socket,指定需要連接的服務器的地址和端口號

2、連接建立後,通過輸出流向服務器發送請求信息

3、通過輸入流獲取服務器響應的信息

4、關閉相關資源

以下例子的解釋:

服務器向客戶端發送請求;

客戶端獲取輸出流 攜帶數據"用戶名:admin;密碼:123"

服務器獲取輸入流 得到客戶端發送的數據;

服務器獲取輸出流  攜帶數據"歡迎您!"

客戶端獲取輸入流 得到服務器發送的數據;

1實現在服務器端獲取客戶端發送的信息,端口號8888

服務器端Server

//1、創建ServerSocket,綁定監聽端口
ServerSocket serverSocket=new ServerSocket(8888);//建議使用1024往後的端口
//2、通過accept方法監聽客戶端請求,等待客戶端的連接
System.out.println("————服務器即將開啓,等待客戶端的連接");
Socket socket=serverSocket.accept();//獲取客戶端發送的Socket實例,用於監聽
//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();//關閉輸入流
//5、關閉相關資源
br.close();
isr.close();
is.close();
serverSocket.close();
socket.close();

客戶端Client

//1、創建Socket,指定需要連接的服務器的地址和端口號
Socket socket=new Socket("localhost",8888);
//2、連接建立後,通過輸出流向服務器發送請求信息
OutputStream os=socket.getOutputStream();//字節輸出流
PrintWriter pw=new PrintWriter(os);//將輸出流包裝爲打印流
pw.write("用戶名:admin;密碼:123");
pw.flush();//刷新緩存,向服務器端發送信息
socket.shutdownOutput();//關閉輸出流
//4、關閉相關資源
pw.close();
os.close();
socket.close();

2實現在服務器端獲取客戶端發送的信息並對客戶端做出響應,端口號8888

——Server結果——

 

——Client結果——

 

服務器端Server

//1、創建ServerSocket,綁定監聽端口
ServerSocket serverSocket=new ServerSocket(8888);//建議使用1024往後的端口
//2、通過accept方法監聽客戶端請求,等待客戶端的連接
System.out.println("————服務器即將開啓,等待客戶端的連接");
Socket socket=serverSocket.accept();//獲取客戶端發送的Socket實例,用於監聽
//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);//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();
serverSocket.close();
socket.close();

客戶端Client

//1、創建Socket,指定需要連接的服務器的地址和端口號
Socket socket=new Socket("localhost",8888);
//2、連接建立後,通過輸出流向服務器發送請求信息
OutputStream os=socket.getOutputStream();//字節輸出流
PrintWriter pw=new PrintWriter(os);//將輸出流包裝爲打印流
pw.write("用戶名:admin;密碼:123");
pw.flush();//刷新緩存,向服務器端發送信息
socket.shutdownOutput();//關閉輸出流
//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);//info爲從服務器獲取的信息
}
//4、關閉相關資源
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();

多線程服務器步驟:實現服務器與多客戶端之間的通信

1、服務器端創建ServerSocket,循環調用accept等待客戶端的連接

2、客戶端創建一個Socket並請求和服務器連接

3、服務器接受客戶端請求,創建socket與客戶端建立專線連接

4、建立連接的兩個socket在一個單獨的線程上對話

5、服務器端繼續等待新的連接

3通過循環監聽等待客戶端,開啓服務器端線程處理類來實現多客戶端通信

——Server結果——

 

——Client結果——

  

服務器端Server

// 1、創建ServerSocket,綁定監聽端口
ServerSocket serverSocket = new ServerSocket(8888);// 建議使用1024往後的端口
// 2、通過accept方法監聽客戶端請求,等待客戶端的連接
Socket socket = null;
int count = 0;// 記錄客戶端數量
System.out.println("————服務器即將開啓,等待客戶端的連接——");
while (true) {// 循環監聽等待客戶端的連接
socket = serverSocket.accept();// 獲取客戶端發送的Socket實例,用於監聽
// 創建一個新線程
ServerThread serverThread = new ServerThread(socket);
// 啓動線程
serverThread.start();
count++;
System.out.println("客戶端的數量:" + count);
//可以通過InetAddress獲取客戶端IP
InetAddress address=socket.getInetAddress();
System.out.println("當前客戶端的IP:"+address.getHostAddress());
}
// serverSocket.close();

服務器端線程處理類ServerThread extends Thread

@Override
public void run() {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
String info = null;
OutputStream os = null;
PrintWriter pw = null;
try {
// 3、連接建立後,通過輸入流讀取客戶端發送的請求信息(通過客戶端的輸入流讀取客戶端的信息)
is = socket.getInputStream();// 獲取字節輸入流
isr = new InputStreamReader(is);// 轉換字節流爲字符流
br = new BufferedReader(isr);// 爲字符輸入流添加緩衝
while ((info = br.readLine()) != null) {// 循環獲取客戶端的信息
System.out.println("我是服務器,客戶端說:" + info);// info爲從客戶端獲取的信息
}
socket.shutdownInput();// 關閉輸入流
// 4、通過輸出流向客戶端發送響應的信息
os = socket.getOutputStream();
pw = new PrintWriter(os);// 與客戶端發送信息類似
pw.write("歡迎您!");
pw.flush();
 
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 5、關閉相關資源
try {
if (pw != null)
pw.close();
if (os != null)
os.close();
if (br != null)
br.close();
if (isr != null)
isr.close();
if (is != null)
is.close();
if (socket != null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

客戶端Client同上

——以下是Socket基於UDP/IP協議的——

服務器端步驟:

1、創建DatagramSocket指定端口號

2、創建DatagramPacket

3、接收客戶端發送的數據信息

4、讀取數據

客戶端步驟:

1、定義發送信息

2、創建DatagramPacket,包含要發送的信息

3、創建DatagramSocket

4、發送數據

1服務器接收客戶端發送的數據,向客戶端響應數據,端口號8800

——UDPServer結果——


——UDPClient結果——

 

服務器UDPServer

/**
 * 服務器接收客戶端發送的數據
 */
//1、創建DatagramSocket指定端口號
DatagramSocket socket=new DatagramSocket(8800);
//2、創建DatagramPacket
byte[] data=new byte[2014];//創建字節數組指定接收的數據報的大小
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();

客戶端UDPClient

/**
 * 向服務器發送數據
 */
//1、定義發送信息
InetAddress address=InetAddress.getByName("localhost");
int port=8800;//端口號
byte[] data="用戶名:admin;密碼:123".getBytes();
//2、創建DatagramPacket,包含要發送的信息
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();

關於多線程與TCP同理

注意:

多線程優先級

是否關閉輸入輸出流(socket已經關閉就無需關閉其它流)

TCP通信傳輸對象Object(ObjectOutputStream)和文件File(FileOutputStream)

https://github.com/xian131/LittleDemoJava.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章