溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java?TCP編程之Scoket是什么及怎么使用

發(fā)布時間:2022-11-07 09:23:39 來源:億速云 閱讀:145 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下Java TCP編程之Scoket是什么及怎么使用的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

一、什么是Scoket

Socket 是一個抽象概念,一個應(yīng)用程序通過一個 Socket 來建立一個遠(yuǎn)程連接,而 Socket 內(nèi)部通 過 TCP/IP 協(xié)議把數(shù)據(jù)傳輸?shù)骄W(wǎng)絡(luò)。

┌───────────┐                                   ┌───────────┐
│Application│                                   │Application│
├───────────┤                                   ├───────────┤
│  Socket   │                                   │  Socket   │
├───────────┤                                   ├───────────┤
│    TCP    │                                   │    TCP    │
├───────────┤      ┌──────┐       ┌──────┐      ├───────────┤
│    IP     │<────>│Router│<─────>│Router│<────>│    IP     │
└───────────┘      └──────┘       └──────┘      └───────────┘

Socket 、 TCP 和部分 IP 的功能都是由操作系統(tǒng)提供的,不同的編程語言只是提供了對操作系統(tǒng)調(diào) 用的簡單的封裝。例如, Java 提供的幾個 Socket 相關(guān)的類就封裝了操作系統(tǒng)提供的接口: Server Socket 類、 Socket 類。

為什么需要 Socket 進(jìn)行網(wǎng)絡(luò)通信?因?yàn)閮H僅通過 IP 地址進(jìn)行通信是不夠的,同 一臺計(jì)算機(jī)同一時間會運(yùn)行多個網(wǎng)絡(luò)應(yīng)用程序,例如瀏覽器、QQ、郵件客戶端等。當(dāng) 操作系統(tǒng)接收到一個數(shù)據(jù)包的時候,如果只有 IP 地址,它沒法判斷應(yīng)該發(fā)給哪個應(yīng)用 程序,所以,操作系統(tǒng)抽象出 Socket 接口,每個應(yīng)用程序需要各自對應(yīng)到不同的 S ocket ,數(shù)據(jù)包才能根據(jù) Socket 正確地發(fā)到對應(yīng)的應(yīng)用程序。

一個 Socket 就是由IP地址和端口號(范圍是0~65535)組成,可以把 Socket 簡單理解為 IP 地址加端口號。端口號總是由操作系統(tǒng)分配,它是一個 0 ~ 65535 之間的數(shù)字,其中,小于 1024 的端口屬于特權(quán)端口,需要管理員權(quán)限,大于 1024 的端口可以由任意用戶的應(yīng)用程序打開。

使用 Socket 進(jìn)行網(wǎng)絡(luò)編程時,本質(zhì)上就是兩個進(jìn)程之間的網(wǎng)絡(luò)通信。其中一個進(jìn) 程必須充當(dāng)服務(wù)器端,它會主動監(jiān)聽某個指定的端口,另一個進(jìn)程必須充當(dāng)客戶端,它 必須主動連接服務(wù)器的 IP 地址和指定端口,如果連接成功,服務(wù)器端和客戶端就成功 地建立了一個 TCP 連接,雙方后續(xù)就可以隨時發(fā)送和接收數(shù)據(jù)。

當(dāng) Socket 連接成功地在服務(wù)器端和客戶端之間建立后:

  • 對服務(wù)器端來說,它的 Socket 是指定的 IP 地址和指定的端口號;

  • 對客戶端來說,它的 Socket 是它所在計(jì)算機(jī)的 IP 地址和一個由操作系統(tǒng)分配的隨機(jī)端口號。

二、服務(wù)器端

package com.ljl.tcp.demo2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class ChatServer {
	public static void main(String[] args) {
		Map<String, String> chatMap = new HashMap<String, String>(){
			{
				put("你好", "你好呀");
				put("hi", "hi~");
				put("hello", "哈嘍");
				put("吃了嗎", "沒呢,你呢");
				put("孤勇者", "愛你孤身走暗巷");
				put("有請潘周聃", "潘周聃,今年29歲,蘇黎世理工大學(xué).....");
				put("很高興認(rèn)識你", "我也是哦");
			}
		};
		try (ServerSocket server = new ServerSocket(9966)) {
			while(true) {
			//客戶端連接
			Socket client = server.accept();
			//獲取客戶端IP地址
			String clientIP = client.getInetAddress().getHostAddress();
			try(
			BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));){	
			//獲取客戶端提問
			String question = reader.readLine();
			System.out.println("服務(wù)器來自客戶端"+clientIP+"的提問:"+question);
			//獲取問題答案
			String answer = chatMap.get(question);
			answer = answer == null?"我不知道你在說啥":answer;
			//發(fā)送答案至客戶端
			writer.write(answer);
			}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

三、客戶端

package com.ljl.tcp.demo2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class ChatClient {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		while(true) {
		try (//創(chuàng)建Socket
		 Socket client = new Socket("192.168.254.163",9966);
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));	
			BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			){
			//獲取控制臺的輸入問題
			String question = input.nextLine();
			if(question.equals("退下")) {
				break;
			}
			//發(fā)送問題至服務(wù)器
			writer.write(question);
			writer.flush();
			//暫時結(jié)束本次輸入
			client.shutdownOutput();
			//獲取來自服務(wù)器的答案
			String answer = reader.readLine();
			System.out.println("服務(wù)器回答:"+answer);
		} catch (IOException e) {
			e.printStackTrace();
		}
		}
		System.out.println("over");
	}
}

Java?TCP編程之Scoket是什么及怎么使用

四、Socket流

當(dāng) Socket 連接創(chuàng)建成功后,無論是服務(wù)器端,還是客戶端,我們都使用 Socket 實(shí)例進(jìn)行網(wǎng)絡(luò)通信。因?yàn)?T CP 是一種基于流的協(xié)議,因此, Java 標(biāo)準(zhǔn)庫使用 InputStream 和 OutputStream 來封裝 Socket 的數(shù)據(jù)流,這 樣我們使用 Socket 的流,和普通 IO 流類似:

// 用于讀取網(wǎng)絡(luò)數(shù)據(jù):
InputStream in = sock.getInputStream();
// 用于寫入網(wǎng)絡(luò)數(shù)據(jù):
OutputStream out = sock.getOutputStream();

寫入網(wǎng)絡(luò)數(shù)據(jù)時,必須要調(diào)用 flush() 方法。如果不調(diào)用 flush() ,我們很可能會發(fā)現(xiàn),客戶端和服務(wù)器都 收不到數(shù)據(jù),這并不是 Java 標(biāo)準(zhǔn)庫的設(shè)計(jì)問題,而是我們以流的形式寫入數(shù)據(jù)的時候,并不是一寫入就立刻發(fā)送 到網(wǎng)絡(luò),而是先寫入內(nèi)存緩沖區(qū),直到緩沖區(qū)滿了以后,才會一次性真正發(fā)送到網(wǎng)絡(luò),這樣設(shè)計(jì)的目的是為了提高 傳輸效率。如果緩沖區(qū)的數(shù)據(jù)很少,而我們又想強(qiáng)制把這些數(shù)據(jù)發(fā)送到網(wǎng)絡(luò),就必須調(diào)用 flush() 強(qiáng)制把緩沖區(qū)數(shù) 據(jù)發(fā)送出去。

以上就是“Java TCP編程之Scoket是什么及怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI