Java 全面掌握網絡編程篇

計算機網絡

是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備,通過通信線路連接起來,在網絡操作系統,網絡管理軟件及網絡通信協議的管理和協調下,實現資源共享和信息傳遞的計算機系統。包括局域網(intranet)和廣域網(internet)

網絡模型

網絡模型一般是指
○ OSI(Open System Interconnection開放系統互連)參考模型
○ TCP/IP參考模型
網絡編程 就是用來實現網絡互聯的不同計算機上運行的程序間可以進行數據交換。
計算機網絡之間以何種規則進行通信,就是網絡模型研究問題

在這裡插入圖片描述

客戶機服務器模式(Client/Server)

●為瞭實現兩臺計算機的通信,必須要用一個網絡線路連接兩臺計算機。
● 服務器(Server)是指提供信息的計算機或程序
●客戶機(Client)是指請求信息的計算機或程序
●網絡用於連接服務器與客戶機,實現兩者相互通信。

在這裡插入圖片描述

TCP/IP的概念和實現

TCP/IP:Transmission Control Protocol/Internet Protocol的簡寫。TCP 是傳輸控制協議的縮寫,它保障瞭兩個應用程序之間的可靠通信。通常用於互聯網協議,被稱 TCP / IP。

TCP三次握手(Three-way handshake)

所謂的“三次握手”即對每次發送的數據量是怎樣跟蹤進行協商使數據段的發送和接收同步,根據所接收到的數據量而確定的數據確認數及數據發送、接收完畢後何時撤消聯系,並建立連接。
❤ 第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SENT狀態,等待服務器確認;
SYN:同步序列編號(Synchronize Sequence Numbers)。
❤ 第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(seq=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
❤ 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ETABLISHED(TCP連接成功)狀態,完成三次握手。
❤ 完成三次握手,客戶端與服務器開始傳送數據

在這裡插入圖片描述

TCP編程

套接字(Socket)是使用TCP提供瞭兩臺計算機之間的通信機制。
客戶端程序創建一個套接字,並嘗試連接服務器的套接字。
當連接建立時,服務器會創建一個 Socket 對象。客戶端和服務器現在可以通過對
Socket 對象的寫入和讀取來進行通信。
► 服務端:
創建服務端對象,監聽一個端口

ServerSocket ss = new ServerSocket(100);

獲取客戶端對象

Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();

► 客戶端:
創建客戶端socket服務,把ip和端口作為地址傳進構造函數

Socket s = new Socket("localhost",100);

UDP的概念和實現

UDP(User Datagram Protocol):UDP 是用戶數據報協議的縮寫,一個無連接的協議。提供瞭應用程序之間要發送的數據的數據包。
用戶數據包協議(UDP)是網絡信息傳輸的另一種形式,基於UDP的通信與基於TCP的通信不同,UDP的信息傳遞更快,但不提供可靠的保證。

UDP編程

發送端:
建立udp服務,發送端沒有指定端口,會自動分配一個端口
DatagramSocket ds = new DatagramSocket();
定義數據內容,並將數據封裝成包
byte[] bt = “hello,udp,我來瞭”.getBytes();
把要發送的數據和ip、port封裝到數據包裡
DatagramPacket db = new
DatagramPacket(bt,bt.length,InetAddress.getByName(“192.168.1.105”),10000);
通過udp的socket服務中的功能完成數據包的發送 ds.send(db);
接收端:定義socket服務,監聽端口
DatagramSocket ds = new DatagramSocket(10000);
預先定義好一個數據包,用於存儲接收到的數據
byte[] bt = new byte[1024];
創建數據包對象,用於接收數據
DatagramPacket dp = new
DatagramPacket(bt,bt.length);
使用socket服務的receive方法將接受到的數據存儲到數據包中
ds.receive(dp);
通過數據包對象,獲取數據包內容
byte[] data = dp.getData();
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();

TCP和UDP的區別

TCP:
1,面向連接的協議,在socket之間進行數據傳輸之前必然要建立連接,所以在TCP中需要連接時間。
2,TCP傳輸數據無大小限制,一旦連接建立起來,雙方的socket就可以按統一的格式傳輸大的數據。
3,TCP是一個可靠的協議,它確保接收方完全正確地獲取發送方所發送的全部數據。
UDP:
1,每個數據報中都給出瞭完整的地址信息,因此無需要建立發送方和接收方的連接。
2,UDP傳輸數據時是有大小限制的,每個被傳輸的數據報必須限定在64KB之內。
3,UDP是一個不可靠的協議,發送方所發送的數據報並不一定以相同的次序到達接收方

TCP和UDP最大的區別在於是否需要客戶端與服務端建立連接後才能進行數據傳輸。

聊天室

服務器處理線程

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;

public class ServerTask  implements Runnable{
	
	
	private Socket socket;

	
	public ServerTask(Socket socket) {
		// TODO 自動生成的構造函數存根
		this.socket = socket;
	
	}
	
	@Override
	public void run() {
		// TODO 自動生成的方法存根
		
		//建立通信後所執行的內容
		
		System.out.println("歡迎【"+socket.getRemoteSocketAddress().toString()+"】進入聊天室");
		
		//構建讀取緩沖
		BufferedReader br =null;
		//http響應寫入
		PrintWriter pw = null;
		
		try {
			
			//獲取客戶端輸入的信息 字節流緩沖成字符流
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			String msg;
			
			while((msg=br.readLine()) != null) {
				msg = "【"+socket.getRemoteSocketAddress().toString()+"】說"+msg;
				
				//輸出客戶端信息
				System.out.println(msg);
				
				//服務器接收到客戶端的消息發送消息給客戶端
				Scanner scanner = new Scanner(System.in);
				System.out.println("請輸入要發送的信息!");
				
				
				pw = new PrintWriter(socket.getOutputStream(),true);
				pw.println("服務器說:"+scanner.nextLine());
				pw.flush();				
			}	
		}catch (SocketException e) {
			// TODO: handle exception
			System.out.println(socket.getRemoteSocketAddress().toString()+"退出聊天室!");
		}	
		catch (Exception e) {
			// TODO: handle exception
		}
		
	}

}

客戶端處理線程

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;


public class ClientTask  implements Runnable{

	private Socket socket;
	
	
	
	public ClientTask(Socket socket) {
		// TODO 自動生成的構造函數存根
		this.socket = socket;
	}
	
	
	@Override
	public void run() {
		// TODO 自動生成的方法存根
		
		try {
				while(true) {
					Scanner scanner = new Scanner(System.in);
					System.out.println("請輸入要發送的信息");
					//消息發送到服務器
					
					PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
					
					//br.readLine()讀取的消息發送到服務器
					pw.println(scanner.nextLine());

					
					//讀取服務器發送的消息
					BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
					System.out.println(br.readLine());

				}		
		}
		catch (Exception e) {
			// TODO: handle exception
		}
		
		
		
	}

	
}

服務器

import java.net.ServerSocket;
import java.net.Socket;

import com.qingsu.chat.Task.ServerTask;

public class ChatServer {

	
	public static void main(String[] args) {
		try {
			
			//創建服務端對象 監聽一個窗口
			ServerSocket serverSocket = new ServerSocket(10622);
			System.out.println("服務器創建成功!端口號"+10622);
			
			//阻塞 直到有鏈接返回
			while(true) {
				Socket socket = serverSocket.accept();//獲取客戶端對象
				
				//啟動一個線程處理該鏈接
				
				Thread thread = new Thread(new ServerTask(socket));
				thread.start();
				
			}		
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

客戶端

import java.net.Socket;

import com.qingsu.chat.Task.ClientTask;

public class ChatClient {
	
	
	public static void main(String[] args) {
		try {
			
			//創建客戶端socket服務,把ip和端口作為地址傳進構造函數
			Socket socket = new Socket("127.0.0.1",10622);
			
			//啟動客戶機線程處理
			Thread thread = new Thread(new ClientTask(socket));		
			thread.start();
		
			
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

}

效果

在這裡插入圖片描述

到此這篇關於Java 全面掌握網絡編程篇的文章就介紹到這瞭,更多相關Java 網絡編程內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: