嵌入式應用軟件開發(fā)做網(wǎng)站排名優(yōu)化的公司
第二十一章 網(wǎng)絡通信
本章節(jié)主要講解的是TCP和UDP兩種通信方式它們都有著自己的優(yōu)點和缺點 ?這兩種通訊方式不通的地方就是TCP是一對一通信 ?UDP是一對多的通信方式 ?接下來會一一講解
TCP通信
TCP通信方式呢 ?主要的通訊方式是一對一的通訊方式,也有著優(yōu)點和缺點 ?它的優(yōu)點對比于UDP來說就是可靠一點 ?因為它的通訊方式是需要先發(fā)送消息 看看客戶端是否能夠接收到消息 如果沒有回復消息的話 服務端 ?就不會發(fā)出文件 等待客戶端回復消息,這個握手模式的話 ?就會非常可靠 ?以下代碼進行講解:
客戶端代碼:
package tcp;
?
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
?
/**
?* Socket客戶端
?**/
public class SocketClient {
? ? public static void main(String[] args) {
? ? ? ? Socket s = null;
? ? ? ? try {
? ? ? ? ? ? // 與ip為127.0.0.1、端口為12345的服務端建立連接
? ? ? ? ? ? s = new Socket("127.0.0.1", 12345);
?
? ? ? ? ? ? // 創(chuàng)建輸入流接收服務端發(fā)送的消息(字節(jié)流)
? ? ? ? ? ? InputStream is = s.getInputStream();
? ? ? ? ? ? // 將服務端返回的字節(jié)流轉化為字符流
? ? ? ? ? ? InputStreamReader isr = new InputStreamReader(is);
? ? ? ? ? ? // 創(chuàng)建字符流讀取緩沖區(qū),方便每行讀取
? ? ? ? ? ? BufferedReader br = new BufferedReader(isr);
?
? ? ? ? ? ? // 創(chuàng)建輸出流返回消息
? ? ? ? ? ? OutputStream os = s.getOutputStream();
? ? ? ? ? ? // 創(chuàng)建輸出流緩沖
? ? ? ? ? ? PrintWriter pw = new PrintWriter(os);
?
? ? ? ? ? ? // 創(chuàng)建發(fā)送消息的線程
? ? ? ? ? ? Runnable rOut = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 接收控制臺輸入
? ? ? ? ? ? ? ? ? ? ? ? Scanner scan = new Scanner(System.in);
? ? ? ? ? ? ? ? ? ? ? ? String msg = scan.nextLine();
? ? ? ? ? ? ? ? ? ? ? ? // 將輸入寫入緩沖
? ? ? ? ? ? ? ? ? ? ? ? pw.println(msg);
? ? ? ? ? ? ? ? ? ? ? ? // 將緩沖內的數(shù)據(jù)推送至服務端并清空緩沖區(qū)
? ? ? ? ? ? ? ? ? ? ? ? pw.flush();
? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 創(chuàng)建接收消息的線程
? ? ? ? ? ? Runnable rIn = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 逐行讀取服務端返回的消息并打印
? ? ? ? ? ? ? ? ? ? ? ? String str = br.readLine();
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("服務端的消息:" + str);
? ? ? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 啟動兩個線程
? ? ? ? ? ? Thread tOut = new Thread(rOut);
? ? ? ? ? ? Thread tIn = new Thread(rIn);
? ? ? ? ? ? tOut.start();
? ? ? ? ? ? tIn.start();
? ? ? ? }catch (IOException e) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 釋放資源
? ? ? ? ? ? ? ? s.close();
? ? ? ? ? ? } catch (Exception exception) {
? ? ? ? ? ? ? ? exception.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
服務端代碼:
package tcp;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
?
/**
?* Socket服務端
?**/
public class SocketServer {
? ? public static void main(String[] args) {
? ? ? ? ServerSocket ss = null;
? ? ? ? Socket s = null;
? ? ? ? try {
? ? ? ? ? ? // 創(chuàng)建監(jiān)聽端口為12345的Socket服務端
? ? ? ? ? ? ss = new ServerSocket(12345);
? ? ? ? ? ? System.out.println("服務端Socket服務已建立,等待客戶端連接...");
? ? ? ? ? ? // 通過ss.accept()開始持續(xù)監(jiān)聽12345端口,當有連接時獲取收到的包裝成Socket的客戶端對象
? ? ? ? ? ? s = ss.accept();
? ? ? ? ? ? // 獲取客戶端的IP地址和端口號
? ? ? ? ? ? String ip = s.getInetAddress().getHostAddress();
? ? ? ? ? ? int port = s.getPort();
? ? ? ? ? ? System.out.println("服務端與 " + ip + ":" + port + " 已建立連接");
?
? ? ? ? ? ? // 創(chuàng)建輸入流接收客戶端發(fā)送的消息(字節(jié)流)
? ? ? ? ? ? InputStream is = s.getInputStream();
? ? ? ? ? ? // 將客戶端發(fā)送的字節(jié)流轉化為字符流
? ? ? ? ? ? InputStreamReader isr = new InputStreamReader(is);
? ? ? ? ? ? // 創(chuàng)建字符流讀取緩沖區(qū),方便每行讀取
? ? ? ? ? ? BufferedReader br = new BufferedReader(isr);
?
? ? ? ? ? ? // 創(chuàng)建輸出流返回消息
? ? ? ? ? ? OutputStream os = s.getOutputStream();
? ? ? ? ? ? // 創(chuàng)建輸出流緩沖
? ? ? ? ? ? PrintWriter pw = new PrintWriter(os);
?
? ? ? ? ? ? // 創(chuàng)建接受信息的線程
? ? ? ? ? ? Runnable rIn = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 逐行讀取客戶端發(fā)送的消息并打印
? ? ? ? ? ? ? ? ? ? ? ? String str = br.readLine();
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("客戶端的消息:" + str);
? ? ? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 創(chuàng)建發(fā)送消息的線程
? ? ? ? ? ? Runnable rOut = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 接收控制臺輸入
? ? ? ? ? ? ? ? ? ? ? ? Scanner scan = new Scanner(System.in);
? ? ? ? ? ? ? ? ? ? ? ? String msg = scan.nextLine();
? ? ? ? ? ? ? ? ? ? ? ? // 將輸入寫入緩沖
? ? ? ? ? ? ? ? ? ? ? ? pw.println(msg);
? ? ? ? ? ? ? ? ? ? ? ? // 將緩沖內的數(shù)據(jù)推送至客戶端并清空緩沖區(qū)
? ? ? ? ? ? ? ? ? ? ? ? pw.flush();
? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 開啟兩個線程
? ? ? ? ? ? Thread tIn = new Thread(rIn);
? ? ? ? ? ? Thread tOut = new Thread(rOut);
? ? ? ? ? ? tIn.start();
? ? ? ? ? ? tOut.start();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 釋放資源
? ? ? ? ? ? ? ? ss.close();
? ? ? ? ? ? ? ? s.close();
? ? ? ? ? ? } catch (Exception exception) {
? ? ? ? ? ? ? ? exception.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
服務端代碼圖已經(jīng)客戶端的代碼圖:
運行結果圖如下所示:
缺點也從而發(fā)現(xiàn) TCP程序是一對一的通信而如果碰到了需要發(fā)通知給好幾個的話 這樣的話需要重復這些操作這樣就會很麻煩 ?所以這里就需要使用到UDP通信 一對多來通信 下一個博客將會講解UDP一對多通信
?