亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中Socket用法詳解

 更新時間:2021年12月16日 16:24:56   作者:石碩頁  
本文詳細講解了Java中Socket的用法,文中通過示例代碼介紹的非常詳細。對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1 問題引入

1.1 網(wǎng)絡(luò)架構(gòu)模型

網(wǎng)絡(luò)架構(gòu)模型主要有OSI參考模型和TCP/IP五層模型

1.1.1 OSI參考模型

OSI(Open System Interconnect),即開放式系統(tǒng)互聯(lián)。一般都叫OSI參考模型,是ISO(國際標準化組織)組織在1985年研究的網(wǎng)絡(luò)互連模型。ISO為了更好的使網(wǎng)絡(luò)應(yīng)用更為普及,推出了OSI參考模型,這樣所有的公司都按照統(tǒng)一的標準來指定自己的網(wǎng)絡(luò),就可以互通互聯(lián)了。

OSI定義了網(wǎng)絡(luò)互連的七層框架(物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會話層、表示層、應(yīng)用層)。

1.1.2 TCP/IP五層模型

TCP/IP五層協(xié)議(物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層)

1.1.3 各協(xié)議層的說明

應(yīng)用層

應(yīng)用層最靠近用戶的一層,是為計算機用戶提供應(yīng)用接口,也為用戶直接提供各種網(wǎng)絡(luò)服務(wù)。我們常見應(yīng)用層的網(wǎng)絡(luò)服務(wù)協(xié)議有:HTTP,HTTPS,F(xiàn)TP,TELNET等。

傳輸層

建立了主機端到端的鏈接,傳輸層的作用是為上層協(xié)議提供端到端的可靠和透明的數(shù)據(jù)傳輸服務(wù),包括處理差錯控制和流量控制等問題。該層向高層屏蔽了下層數(shù)據(jù)通信的細節(jié),使高層用戶看到的只是在兩個傳輸實體間的一條主機到主機的、可由用戶控制和設(shè)定的、可靠的數(shù)據(jù)通路。我們通常說的,TCP UDP就是在這一層。端口號既是這里的“端”。

網(wǎng)絡(luò)層

本層通過IP尋址來建立兩個節(jié)點之間的連接,為源端的運輸層送來的分組,選擇合適的路由和交換節(jié)點,正確無誤地按照地址傳送給目的端的運輸層。就是通常說的IP層。這一層就是我們經(jīng)常說的IP協(xié)議層。IP協(xié)議是Internet的基礎(chǔ)。

1.2 網(wǎng)絡(luò)編程中的問題

常見的網(wǎng)絡(luò)編程中的問題主要是怎么定位網(wǎng)絡(luò)上的一臺主機或多臺主機,另一個是定位后如何進行數(shù)據(jù)的傳輸。對于前者,在網(wǎng)絡(luò)層中主要負責網(wǎng)絡(luò)主機的定位,數(shù)據(jù)傳輸?shù)穆酚?,由IP地址可以唯一地確定Internet上的一臺主機。對于后者,在傳輸層則提供面向應(yīng)用的可靠(tcp)的或非可靠(UDP)的數(shù)據(jù)傳輸機制。

對于客戶端/服務(wù)器(C/S)結(jié)構(gòu)。 即通信雙方一方作為服務(wù)器等待客戶提出請求并予以響應(yīng)??蛻魟t在需要服務(wù)時向服務(wù)器提出申請。服務(wù)器一般作為守護進程始終運行,監(jiān)聽網(wǎng)絡(luò)端口,一旦有客戶請求,就會啟動一個服務(wù)進程來響應(yīng)該客戶,同時自己繼續(xù)監(jiān)聽服務(wù)端口,使后來的客戶也能及時得到服務(wù)。

對于瀏覽器/服務(wù)器(B/S)結(jié)構(gòu)。 客戶則在需要服務(wù)時向服務(wù)器進行請求。服務(wù)器響應(yīng)后及時返回,不需要實時監(jiān)聽端口。

1.3 TCP協(xié)議與UDP協(xié)議

1.3.1 TCP

TCP是(Tranfer Control Protocol)的簡稱,是一種面向連接的保證可靠傳輸?shù)膮f(xié)議。通過TCP協(xié)議傳輸,得到的是一個順序的無差錯的數(shù)據(jù)流。發(fā)送方和接收方的成對的兩個socket之間必須建立連接,當一個socket(通常都是server socket)等待建立連接時,另一個socket可以要求進行連接,一旦這兩個socket連接起來,它們就可以進行雙向數(shù)據(jù)傳輸,雙方都可以進行發(fā)送或接收操作。

TCP的三次握手

建立起一個TCP連接需要經(jīng)過“三次握手”:第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進入SYN_SEND狀態(tài),等待服務(wù)器確認;第二次握手:服務(wù)器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包,此時服務(wù)器進入SYN_RECV狀態(tài);第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進入ESTABLISHED狀態(tài),完成三次握手。

握手過程中傳送的包里不包含數(shù)據(jù),三次握手完畢后,客戶端與服務(wù)器才正式開始傳送數(shù)據(jù)。理想狀態(tài)下,TCP連接一旦建立,在通信雙方中的任何一方主動關(guān)閉連接之前,TCP?連接都將被一直保持下去。斷開連接時服務(wù)器和客戶端均可以主動發(fā)起斷開TCP連接的請求。

1.3.2 UDP

UDP是(User Datagram Protocol)的簡稱,是一種無連接的協(xié)議,每個數(shù)據(jù)報都是一個獨立的信息,包括完整的源地址或目的地址,它在網(wǎng)絡(luò)上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內(nèi)容的正確性都是不能被保證的。

1.3.3 TCP和UDP的區(qū)別

UDP:
  • 1、每個數(shù)據(jù)報中都給出了完整的地址信息,因此無需要建立發(fā)送方和接收方的連接。
  • 2、UDP傳輸數(shù)據(jù)時是有大小限制的,每個被傳輸?shù)臄?shù)據(jù)報必須限定在64KB之內(nèi)。
  • 3、UDP是一個不可靠的協(xié)議,發(fā)送方所發(fā)送的數(shù)據(jù)報并不一定以相同的次序到達接收方
TCP:
  • 1、面向連接的協(xié)議,在socket之間進行數(shù)據(jù)傳輸之前必然要建立連接,所以在TCP中需要連接時間。
  • 2、TCP傳輸數(shù)據(jù)沒有大小限制,一旦連接建立起來,雙方的socket就可以按統(tǒng)一的格式傳輸大的數(shù)據(jù)。
  • 3、TCP是一個可靠的協(xié)議,它確保接收方完全正確地獲取發(fā)送方所發(fā)送的全部數(shù)據(jù)。
應(yīng)用:
  • 1、TCP在網(wǎng)絡(luò)通信上有極強的生命力,例如遠程連接(Telnet)和文件傳輸(FTP)都需要不定長度的數(shù)據(jù)被可靠地傳輸。但是可靠的傳輸是要付出代價的,對數(shù)據(jù)內(nèi)容正確性的檢驗必然占用計算機的處理時間和網(wǎng)絡(luò)的帶寬,因此TCP傳輸?shù)男什蝗鏤DP高。
  • 2、UDP操作簡單,而且僅需要較少的監(jiān)護,因此通常用于局域網(wǎng)高可靠性的分散系統(tǒng)中client/server應(yīng)用程序。例如視頻會議系統(tǒng),并不要求音頻視頻數(shù)據(jù)絕對的正確,只要保證連貫性就可以了,這種情況下顯然使用UDP會更合理一些。

2 socket網(wǎng)絡(luò)編程

2.1什么是socket?

Socket的英文原義是“孔”或“插座”。在網(wǎng)絡(luò)編程中,網(wǎng)絡(luò)上的兩個程序通過一個雙向的通信連接實現(xiàn)數(shù)據(jù)的交換,這個連接的一端稱為一個socket。

Socket套接字是通信的基石,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過程中端點的抽象表示,包含進行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機的IP地址,本地進程的協(xié)議端口,遠地主機的IP地址,遠地進程的協(xié)議端口。

Socket本質(zhì)是編程接口(API),對TCP/IP的封裝,TCP/IP也要提供可供程序員做網(wǎng)絡(luò)開發(fā)所用的接口,這就是Socket編程接口;HTTP是轎車,提供了封裝或者顯示數(shù)據(jù)的具體形式;Socket是發(fā)動機,提供了網(wǎng)絡(luò)通信的能力。

2.2 Socket的原理

Socket實質(zhì)上提供了進程通信的端點。進程通信之前,雙方首先必須各自創(chuàng)建一個端點,否則是沒有辦法建立聯(lián)系并相互通信的。正如打電話之前,雙方必須各自擁有一臺電話機一樣。

套接字之間的連接過程可以分為三個步驟:服務(wù)器監(jiān)聽,客戶端請求,連接確認。

  • 1、服務(wù)器監(jiān)聽:是服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡(luò)狀態(tài)。
  • 2、客戶端請求:是指由客戶端的套接字提出連接請求,要連接的目標是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端套接字提出連接請求。
  • 3、連接確認:是指當服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求,它就響應(yīng)客戶端套接字的請求,建立一個新的線程,把服務(wù)器端套接字的描述發(fā)給客戶端,一旦客戶端確認了此描述,連接就建立好了。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求。

3 基于java的socket網(wǎng)絡(luò)編程實現(xiàn)

Server端Listen監(jiān)聽某個端口是否有連接請求,Client端向Server 端發(fā)出連接請求,Server端向Client端發(fā)回Accept接受消息。這樣一個連接就建立起來了。Server端和Client端都可以通過Send,Write等方法與對方通信。

對于一個功能齊全的Socket,都要包含以下基本結(jié)構(gòu),其工作過程包含以下四個基本的步驟:

  • 1、創(chuàng)建Socket;
  • 2、 打開連接到Socket的輸入/出流;
  • 3、按照一定的協(xié)議對Socket進行讀/寫操作;
  • 4、關(guān)閉Socket。

3.1 基于TCP的socket實現(xiàn)

SocketClient.java

public class SocketClient {
	
	public static void main(String[] args) throws InterruptedException {
		try {
			// 和服務(wù)器創(chuàng)建連接
			Socket socket = new Socket("localhost",8088);
			
			// 要發(fā)送給服務(wù)器的信息
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			pw.write("客戶端發(fā)送信息");
			pw.flush();
			
			socket.shutdownOutput();
			
			// 從服務(wù)器接收的信息
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String info = null;
			while((info = br.readLine())!=null){
				System.out.println("我是客戶端,服務(wù)器返回信息:"+info);
			}
			
			br.close();
			is.close();
			os.close();
			pw.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 
}

SocketServer.java

public class SocketServer {
	
	public static void main(String[] args) {
		try {
			// 創(chuàng)建服務(wù)端socket
			ServerSocket serverSocket = new ServerSocket(8088);
			
			// 創(chuàng)建客戶端socket
			Socket socket = new Socket();	
			
			//循環(huán)監(jiān)聽等待客戶端的連接
            while(true){
            	// 監(jiān)聽客戶端
            	socket = serverSocket.accept();
            	
            	ServerThread thread = new ServerThread(socket);
            	thread.start();
            	
            	InetAddress address=socket.getInetAddress();
                System.out.println("當前客戶端的IP:"+address.getHostAddress());
            }
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
 
}

ServerThread.java

public class ServerThread extends Thread{
	
	private Socket socket = null;
	
	public ServerThread(Socket socket) {
		this.socket = socket;
	}
 
	@Override
	public void run() {
		InputStream is=null;
        InputStreamReader isr=null;
        BufferedReader br=null;
        OutputStream os=null;
        PrintWriter pw=null;
        try {
			is = socket.getInputStream();
			isr = new InputStreamReader(is);
			br = new BufferedReader(isr);
			
			String info = null;
			
			while((info=br.readLine())!=null){
				System.out.println("我是服務(wù)器,客戶端說:"+info);
			}
			socket.shutdownInput();
			
			os = socket.getOutputStream();
			pw = new PrintWriter(os);
			pw.write("服務(wù)器歡迎你");
			
			pw.flush();
        } catch (Exception e) {
			// TODO: handle exception
		} finally{
			//關(guān)閉資源
            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) {
                e.printStackTrace();
            }
		}
	}
 
}

在運行時,若先執(zhí)行SocketClient會提示無法連接到服務(wù)器,因為此時沒有服務(wù)在監(jiān)聽8088端口。此demo是多線程實現(xiàn),在先啟動SocketServer后,服務(wù)器會一直監(jiān)聽8088端口,再執(zhí)行SocketClient就會正常輸出結(jié)果。

3.2 基于UDP的socket實現(xiàn)

SocketClient.java

public class SocketClient {
	
	public static void main(String[] args) {
		try {
            // 要發(fā)送的消息
            String sendMsg = "客戶端發(fā)送的消息";
            
            // 獲取服務(wù)器的地址
            InetAddress addr = InetAddress.getByName("localhost");
            
            // 創(chuàng)建packet包對象,封裝要發(fā)送的包數(shù)據(jù)和服務(wù)器地址和端口號
            DatagramPacket packet = new DatagramPacket(sendMsg.getBytes(),
            		sendMsg.getBytes().length, addr, 8088); 
            
            // 創(chuàng)建Socket對象
            DatagramSocket socket = new DatagramSocket();
            
            // 發(fā)送消息到服務(wù)器
            socket.send(packet);
 
            // 關(guān)閉socket
            socket.close();
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
	}
}

SocketServer.java

public class SocketServer {
	
	public static void main(String[] args) {
		try {
			 // 要接收的報文
			byte[] bytes = new byte[1024];
			DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
			
			// 創(chuàng)建socket并指定端口
			DatagramSocket socket = new DatagramSocket(8088);
			
			// 接收socket客戶端發(fā)送的數(shù)據(jù)。如果未收到會一致阻塞
			socket.receive(packet);
			String receiveMsg = new String(packet.getData(),0,packet.getLength());
			System.out.println(packet.getLength());
			System.out.println(receiveMsg);
			
			// 關(guān)閉socket
			socket.close();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
 
}

運行時,先啟動SocketServer,再啟動SocketClient,會正常打印數(shù)據(jù)。在先啟動SocketServer時,代碼執(zhí)行到socket.receive(packet)時會一致阻塞在這里,直到啟動SocketClient后,SocketServer會繼續(xù)執(zhí)行,并將收到SocketClient的信息打印出來。如果是先啟動SocketClient,會立即執(zhí)行完畢,再執(zhí)行SocketServer時,依舊會阻塞在receive方法處,直到下一次SocketClient的執(zhí)行。

參考

Java Scoket編程

WebSocket與消息推送

JAVA 通過 Socket 實現(xiàn) TCP 編程

OSI七層模型與TCP/IP五層模型

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java TreeUtil菜單遞歸工具類

    java TreeUtil菜單遞歸工具類

    這篇文章主要為大家詳細介紹了java TreeUtil菜單遞歸工具類,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • Java枚舉與注解的創(chuàng)建步驟

    Java枚舉與注解的創(chuàng)建步驟

    這篇文章通過抽象的概念和具體實現(xiàn)步驟,充分說明了java枚舉與注解的概念和使用方法,通過該篇文章你可以學會如何自定義枚舉類和了解部分Java內(nèi)置注解,希望對你有所幫助
    2021-06-06
  • Spring Boot Admin(監(jiān)控工具)的使用

    Spring Boot Admin(監(jiān)控工具)的使用

    今天我們將會講解一個優(yōu)秀的監(jiān)控工具Spring Boot Admin。 它采用圖形化的界面,讓我們的Spring Boot管理更加簡單,需要的朋友可以參考下
    2020-02-02
  • Spring Boot如何整合FreeMarker模板引擎

    Spring Boot如何整合FreeMarker模板引擎

    這篇文章主要介紹了Spring Boot如何整合FreeMarker模板引擎,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • JPA 加鎖機制及@Version版本控制方式

    JPA 加鎖機制及@Version版本控制方式

    這篇文章主要介紹了JPA 加鎖機制及@Version版本控制方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java根據(jù)本地IP獲取mac地址的方法

    java根據(jù)本地IP獲取mac地址的方法

    這篇文章主要為大家詳細介紹了java根據(jù)本地IP獲取mac地址的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 淺談Java自定義注解相關(guān)知識

    淺談Java自定義注解相關(guān)知識

    今天帶大家來學習Java注解的相關(guān)知識,文中對自定義注解作了非常詳細的介紹,對正在學習Java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • Java使用Sftp和Ftp實現(xiàn)對文件的上傳和下載

    Java使用Sftp和Ftp實現(xiàn)對文件的上傳和下載

    這篇文章主要介紹了Java使用Sftp和Ftp實現(xiàn)對文件的上傳和下載,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • java發(fā)送http get請求的兩種方法(總結(jié))

    java發(fā)送http get請求的兩種方法(總結(jié))

    下面小編就為大家?guī)硪黄猨ava發(fā)送http get請求的兩種方法(總結(jié))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • springcloud?nacos動態(tài)線程池Dynamic?tp配置接入實戰(zhàn)詳解

    springcloud?nacos動態(tài)線程池Dynamic?tp配置接入實戰(zhàn)詳解

    這篇文章主要為大家介紹了springcloud?nacos動態(tài)線程池Dynamic?tp配置接入實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12

最新評論