Java網絡通信TCP

目錄

TCP兩個核心類

服務端

1.用ServerSocker類創建對象并且手動指定端口號

2.accept阻塞連接服務端與客戶端

3.給客戶端提供處理業務方法

4.處理業務

整體代碼

客戶端

1.創建Socket對象,并連接服務端的ip與端口號

2.獲取Socket流對象,寫入數據,阻塞等待服務端響應

整體代碼

jconsole用來監控java線程


TCP兩個核心類

ServerSocket 服務器使用socket

accept沒有參數 返回值是一個Socket對象

功能是等待服務器和客戶端建立連接,建立成功后則會把這個連接獲取到進程中。接下來就通過Scoket返回的對象來進行交互

Scoket服務器和客戶端都使用socket

通過socket對象就可以進行發送接收數據

socket內部包含了輸入流對象(接收) 輸出流對象 (發送)

服務端

1.用ServerSocker類創建對象并且手動指定端口號

    private ServerSocket serverSocket=null;public Test1(int port) throws IOException {serverSocket=new ServerSocket(port);

2.accept阻塞連接服務端與客戶端

當我們用UDP那樣連接客戶端會出現一個問題

UDP是無連接的,他發送數據時直接用地址端口號發送

而TCP是有連接的,當我們用accept連接時,ProcessConnect方法會一直被循環執行單個客戶端,而其他客戶端要連接時,無法執行到accept,必須等待ProcessConnect方法執行結束,所以會被阻塞。簡單來說就是當有一個客戶端連接時,其他客戶端必須等待連接的客戶端斷開連接才能連接,還是一個個來連接。

所以ProcessConnect方法我們直接交給線程去執行,這樣其他客戶端來連接時,直接讓線程去執行處理客戶端業務。

所以我們可以用到多線程

既然用到了多線程,就可以用出線程池,效率會更高。

public void start() throws IOException {System.out.println("服務器啟動");while (true){//阻塞等待服務器與客戶端建立連接Socket socket=serverSocket.accept();//若沒線程 當一個客戶端連接后 會一直在ProcessConnect內//其他客戶端連接時 必須要等待ProcessConnect結束,進入下一次循環,才能執行到Socketsocket=serverSocket.accept(); 才能連接下一個客戶端
//           // ProcessConnect(socket);//所以執行處理客戶端請求,我們讓線程去干,這樣就不會在一個線程內阻塞
//            Thread thread=new Thread(()->{
//                try {
//                    ProcessConnect(socket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            thread.start();//線程池ExecutorService executorService= Executors.newCachedThreadPool();executorService.submit(new Runnable() {@Overridepublic void run() {try {ProcessConnect(socket);} catch (IOException e) {throw new RuntimeException(e);}}});}}

3.給客戶端提供處理業務方法

我們可以直接獲取Socket內的流對象,直接寫入讀出即可

需要注意,寫入數據時,因為時流對象接收,要\n等待其他結束,而我們輸入數據時,流對象是不會寫入\n的,所以我們可以在數據后自動添加\n 或者用println默認有個\n

public void ProcessConnect(Socket socket) throws IOException {//實際他們交流數據是一個為socket類型的文件System.out.printf("[地址:%s:端口號%d]建立連接成功\n",socket.getInetAddress().toString(),socket.getPort());try (InputStream inputStream = socket.getInputStream();//獲取socket內部的input流OutputStream outputStream = socket.getOutputStream())//獲取socket內部的output流{Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);//長連接寫法while (true) {if(!scanner.hasNext()){System.out.printf("[地址:%s:端口號%d]斷開連接",socket.getInetAddress().toString(),socket.getPort());}//從客戶端接收數據String resqust = scanner.next();System.out.println("服務器接收數據");//處理數據String response = process(resqust);System.out.println("服務器處理數據");//因為這用流接收 我們按下換行是被scanner接收但并未添加到數據內 而服務器接收流收到的數據內//是沒有換行符的 就會一直阻塞 所以我們要在數據后再加個\n//服務器發送數據//printWriter.write(response+'\n');//或者直接使用println自帶\nprintWriter.println(response);System.out.println("服務器發送數據");//刷新緩沖區printWriter.flush();System.out.printf("[地址:%s:端口號:%d]接收數據:%s 響應數據:%s",socket.getInetAddress().toString(),socket.getPort(),resqust,response);}}}

4.處理業務

這里是為了演示TCP連接,所以只寫個簡單回傳

public String process(String s){return s;}

整體代碼

package TestTCP;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//服務器
public class Test1 {private ServerSocket serverSocket=null;public Test1(int port) throws IOException {serverSocket=new ServerSocket(port);}public void start() throws IOException {System.out.println("服務器啟動");while (true){//阻塞等待服務器與客戶端建立連接Socket socket=serverSocket.accept();//若沒線程 當一個客戶端連接后 會一直在ProcessConnect內//其他客戶端連接時 必須要等待ProcessConnect結束,進入下一次循環,// 才能執行到Socketsocket=serverSocket.accept(); 才能連接下一個客戶端
//            ProcessConnect(socket);//所以執行處理客戶端請求,我們讓線程去干,這樣就不會在一個線程內阻塞
//            Thread thread=new Thread(()->{
//                try {
//                    ProcessConnect(socket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            thread.start();//線程池ExecutorService executorService= Executors.newCachedThreadPool();executorService.submit(new Runnable() {@Overridepublic void run() {try {ProcessConnect(socket);} catch (IOException e) {throw new RuntimeException(e);}}});}}//給當前客戶端提供服務方法public void ProcessConnect(Socket socket) throws IOException {//實際他們交流數據是一個為socket類型的文件System.out.printf("[地址:%s:端口號%d]建立連接成功\n",socket.getInetAddress().toString(),socket.getPort());try (InputStream inputStream = socket.getInputStream();//獲取socket內部的input流OutputStream outputStream = socket.getOutputStream())//獲取socket內部的output流{Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);//長連接寫法while (true) {if(!scanner.hasNext()){System.out.printf("[地址:%s:端口號%d]斷開連接",socket.getInetAddress().toString(),socket.getPort());}//從客戶端接收數據String resqust = scanner.next();System.out.println("服務器接收數據");//處理數據String response = process(resqust);System.out.println("服務器處理數據");//因為這用流接收 我們按下換行是被scanner接收但并未添加到數據內 而服務器接收流收到的數據內//是沒有換行符的 就會一直阻塞 所以我們要在數據后再加個\n//服務器發送數據//printWriter.write(response+'\n');//或者直接使用println自帶\nprintWriter.println(response);System.out.println("服務器發送數據");//刷新緩沖區printWriter.flush();System.out.printf("[地址:%s:端口號:%d]接收數據:%s 響應數據:%s",socket.getInetAddress().toString(),socket.getPort(),resqust,response);}}}public String process(String s){return s;}public static void main(String[] args) throws IOException {Test1 t1=new Test1(8080);t1.start();}
}

客戶端

1.創建Socket對象,并連接服務端的ip與端口號

    private Socket socket=null;public Test2() throws IOException {socket=new Socket("127.0.0.1",8080);

2.獲取Socket流對象,寫入數據,阻塞等待服務端響應

    public void start() throws IOException {try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){while (true){Scanner scanner=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);Scanner scanner1=new Scanner(System.in);System.out.println("輸入數據>");String requst=scanner1.next();//因為這用流接收 我們按下換行是被scanner接收但并未添加到數據內 而服務器接收流收到的數據內//是沒有換行符的 就會一直阻塞 所以我們要在數據后再加個\n//printWriter.write(requst+'\n');//或者直接使用println自帶\nprintWriter.println(requst);//刷新緩沖區printWriter.flush();String response=scanner.next();System.out.println(response);}}finally {socket.close();}}

整體代碼

package TestTCP;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;//客戶端
public class Test2 {private Socket socket=null;public Test2() throws IOException {socket=new Socket("127.0.0.1",8080);}public void start() throws IOException {try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){while (true){Scanner scanner=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);Scanner scanner1=new Scanner(System.in);System.out.println("輸入數據>");String requst=scanner1.next();//因為這用流接收 我們按下換行是被scanner接收但并未添加到數據內 而服務器接收流收到的數據內//是沒有換行符的 就會一直阻塞 所以我們要在數據后再加個\n//printWriter.write(requst+'\n');//或者直接使用println自帶\nprintWriter.println(requst);//刷新緩沖區printWriter.flush();String response=scanner.next();System.out.println(response);}}finally {socket.close();}}public static void main(String[] args) throws IOException {Test2 t2=new Test2();t2.start();}
}

jconsole用來監控java線程

jconsole在路徑 jdk/bin/jconsole.exe

例:

我們需要看util最后一局,可以看出線程是在next阻塞著。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717150.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717150.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux: Network: socket: sendto 如果返回0,是否一定代表發送成功?

最近遇到一個問題,雖然應用層使用的系統調用send已經返回成功,而且沒有錯誤日志產生,也沒有errno的設置。那是不是代表一定是沒有問題?從抓包的結果看,雖然上層應用已經顯示發出去,但是實際抓包的時候&…

[python隊列廣搜]請佩戴好口罩

請佩戴好口罩 題目描述 疫情當下,希望同學們都認真佩戴口罩,保護自己,保護他人。 現假設有一個n*n的網格,每個人分別站在網格中的一個方格上,人們可以選擇佩戴/不佩戴口罩,口罩對于病毒的傳播有如下影響&…

被曝隱瞞添加劑、夸大產品功效,東方甄選再陷選品風波

號稱專注為客戶細心甄選好物的東方甄選((HK:01797)),又攤上事兒了。 近日,海關總署發布公告稱,美國飲料生產企業JERRY&SONS PHARMACEUTICAL INC在申請注冊時提供了虛假材料,且未…

moviepy用法大全

1.引用 from moviepy.editor import * 2. 載入 2.1 載入視頻 video = VideoFileClip(filePath) 2.2 載入音頻 audio=AudioFileClip(filePath) 2.3 載入圖片 img = (ImageClip(videopath+videofengpi) # 水印持續時間 .set_duration(start_video_clip_begin.duration) …

C2_W2_Assignment_吳恩達_中英_Pytorch

Neural Networks for Handwritten Digit Recognition, Multiclass In this exercise, you will use a neural network to recognize the hand-written digits 0-9. 在本次練習中,您將使用神經網絡來識別0-9的手寫數字。 Outline 1 - Packages 2 - ReLU Activatio…

c語言經典測試題9

1.題1 #include <stdio.h> int main() { int i 1; sizeof(i); printf("%d\n", i); return 0; } 上述代碼運行結果是什么呢&#xff1f; 我們來分析一下&#xff1a;其實這題的難點就是sizeof操作后i的結果是否會改變&#xff0c;首先我們創建了一個整型i&a…

LeetCode刷題小記 六、【棧與隊列】

1.棧與隊列 文章目錄 1.棧與隊列寫在前面1.1棧與隊列理論基礎1.2用棧實現隊列1.3用隊列實現棧1.4有效的括號1.5刪除字符串中的所有相鄰重復項1.6逆波蘭表達式求值1.7滑動窗口最大值1.8前K個高頻元素 Reference 寫在前面 本系列筆記主要作為筆者刷題的題解&#xff0c;所用的語…

分布式基礎 --- Leader election

分布式基礎 --- Leader election 為什么需要leader electionRing electionBully Algorithm 為什么需要leader election 在一組集群中, 需要選出一個leader來承擔一些特別的任務, 比如 協調和控制系統操作&#xff1a;領導者負責協調和控制整個分布式系統的操作。它可以接收和處…

one4all 排坑記錄

one4all 排坑記錄 任務踩坑回顧動作踩坑動作踩坑動作新一步測試Habitat-sim 測試habitat-lab繼續ONE4ALL 任務 看了《One-4-All: Neural Potential Fields for Embodied Navigation》這篇論文&#xff0c;感覺挺有意思&#xff0c;他也開源了代碼。視覺語言導航是我一直想做的…

windows上elasticsearch的ik分詞器的安裝

下載 下載地址 在elasticsearch下的plugins文件夾下創建ik的文件夾 下載的ik壓縮包解壓到plugins/ik 重啟elasticsearch 驗證 http://ip:9200/_cat/plugins

python筆記_運算符優先級

運算符描述算術運算符&#xff08;x&#xff09;括號內優先級最高**乘方 * / // % 乘 矩陣乘 除 整除 取余 _ 加 減 位運算符 >> << 右移 左移 &按位與^按位異或|按位或比較運算符 in not in is is not < < > > ! 判斷兩個變量是否相同 判…

SpringBoot3-核心原理

1. 事件和監聽器 1. 生命周期監聽 場景&#xff1a;監聽應用的生命周期 1. 監聽器-SpringApplicationRunListener 自定義SpringApplicationRunListener來監聽事件&#xff1b; 編寫SpringApplicationRunListener 實現類在 META-INF/spring.factories 中配置 org.springfram…

【藍橋杯】錯誤票據

今天是2024年3月1號&#xff0c;藍橋杯比賽還有一個月的時間&#xff0c;雖說自己不指望拿獎吧&#xff0c;但是還是有些莫i名的焦慮&#xff0c;這道題目都做不出來&#xff0c;感覺自己真的有點菜啊&#xff01;但是還好啦&#xff0c;我覺得是因為我沒有題感&#xff0c;慢慢…

spring boot 整合 minio存儲 【使用篇】

導入依賴 <!--minio--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.0.3</version></dependency> yml配置&#xff08;默認配置&#xff09; max-file-size: 200MB 設置文件最大…

華為od機試C卷-開源項目熱度榜單

1、題目描述 某個開源社區希望將最近熱度比較高的開源項目出一個榜單&#xff0c;推薦給社區里面的開發者。 對于每個開源項目&#xff0c;開發者可以進行關注(watch)、收藏(star)、fork、提issue、提交合并請求(MR)等。 數據庫里面統計了每個開源項目關注、收藏、fork、issue…

微服務API網關---APISIX

最近在做微服務調研&#xff0c;看到了apisix這個網關&#xff0c;于是進行了初步了解一下。 微服務是指&#xff0c;將大型應用分解成多個獨立的組件&#xff0c;其中每個組件都各自的負責對應項目。 系統的架構大致經歷了&#xff1a;單體應用架構–> SOA架構 -->微服務…

Linux多線程服務端編程:使用muduo C++網絡庫 學習筆記 附錄D 關于TCP并發連接的幾個思考題與試驗

前幾天作者在新浪微博上出了兩道有關TCP的思考題&#xff0c;引發了一場討論&#xff08;http://weibo.com/1701018393/eCuxDrtaONn&#xff09;。 第一道初級題目是&#xff1a;有一臺機器&#xff0c;它有一個IP&#xff0c;上面運行了一個TCP服務程序&#xff0c;程序只偵聽…

StarRocks實戰——松果出行實時數倉實踐

目錄 一、背景 二、松果出行實時OLAP的演進 2.1 實時數倉1.0的架構 2.2 實時數倉2.0的架構 2.3 實時數倉3.0的架構 三、StarRocks 的引入 四、StarRocks在松果出行的應用 4.1 在訂單業務中的應用 4.2 在車輛方向的應用 4.3 StarRocks “極速統一” 落地 4.4 StarRoc…

Lambda、Function、StreamAPI詳解

目錄 1、Lambda 2、Function 3、StreamAPI 中間操作&#xff1a;Intermediate Operations 終止操作&#xff1a;Terminal Operation 1、Lambda Java8語法糖&#xff1a;參數列表 箭頭 方法體 package com.atguiggu.lambda;import java.util.*; import java.util.funct…

分布式ID生成系統之雪花算法詳解

在當今的云計算和微服務架構盛行的時代&#xff0c;分布式系統已成為軟件開發的重要組成部分。隨著系統規模的擴大和業務的復雜化&#xff0c;對數據一致性和唯一性的要求也越來越高&#xff0c;尤其是在全局唯一標識符&#xff08;ID&#xff09;的生成上。因此&#xff0c;分…