Java實現Socket聊天室

一、網絡編程是什么?

在網絡通信協議下,不同計算機上運行的程序,進行數據傳輸。

  • 應用場景:即時通訊、網游對戰、金融證券、國際貿易、郵件、等等。

不管是什么場景,都是計算機與計算機之間通過網絡進行數據傳輸。

  • Java中可以使用java.net包下的技術輕松開發出常見的網絡應用程序。

二、常見的軟件架構?

  1. 常見的軟件架構有哪些?

    CS/BS。 即Client/Server 和 Browser/Server模式

  2. 通信的軟件架構CS/BS的各有什么優缺點和區別?

    CS:客戶端服務端模式都需要開發客戶端

    BS:瀏覽器服務器模式不需要開發客戶端

    CS:適合定制專業化的辦公類軟件:IDEA、網游

    BS:適合移動互聯網應用,可以在任何地方隨時訪問系統

三、網絡編程三要素?

  • IP:設備在網絡中的地址,是唯一的標識
  • 端口號:應用程序在設備中唯一標識
  • 協議:數據在網絡中傳輸的規則,常見的協議游UDP、TCP、HTTP、HTTPS、FTP

四、Socket編程(Java)

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

java.net.Socket類代表一個套接字,并且java.net.ServerSocket類為服務器程序提供了一種監聽客戶端,并與他們建立連接的機制。

以下步驟在兩臺計算機之間使用Socket建立TCP連接出現:

  • 服務器實例化一個ServerSocket對象,表示通過服務器端口通信。(ServerSocket本質就是監聽端口等待Socket對象連接
  • 服務器調用ServerSocket類的accept()方法,該方法將一直等待,直到一個客戶端連接到服務器上給定的端口。
  • 服務器ServerSocket監聽等待連接的過程中,客戶端創建一個Socket對象,并指定該Socket要連接到的服務器的名稱端口
  • Socket類的構造函數試圖將客戶端連接到指定的服務器和端口號。如果通信被建立,則在客戶端創建一個 Socket 對象能夠與服務器進行通信。
  • 在服務器端,accept() 方法返回服務器上一個新的 socket 引用,該 socket 連接到客戶端的 socket。

在這里插入圖片描述

  1. 連接建立后,通過使用 I/O 流在進行通信,每一個socket都有一個輸出流和一個輸入流客戶端的輸出流連接到服務器端的輸入流,而客戶端的輸入流連接到服務器端的輸出流。
  2. TCP 是一個雙向的通信協議,因此數據可以通過兩個數據流在同一時間發送。

五、ServerSocket類的方法

服務器應用程序通過使用 java.net.ServerSocket 類以獲取一個端口,并且偵聽客戶端請求。

ServerSocket 類有四個構造方法:

序號方法描述
1public ServerSocket(int port) throws IOException 創建監聽特定端口的服務器套接字。
2public ServerSocket(int port, int backlog) throws IOException 利用指定的 backlog 創建服務器套接字并將其綁定到指定的本地端口號。
3public ServerSocket(int port, int backlog, InetAddress address) throws IOException 使用指定的端口、偵聽 backlog 和要綁定到的本地 IP 地址創建服務器。
4public ServerSocket() throws IOException 創建非綁定服務器套接字。

創建非綁定服務器套接字。 如果 ServerSocket 構造方法沒有拋出異常,就意味著你的應用程序已經成功綁定到指定的端口,并且偵聽客戶端請求。

這里有一些 ServerSocket 類的常用方法:

序號方法描述
1public int getLocalPort() 返回此套接字在其上偵聽的端口。
2public Socket accept() throws IOException 偵聽并接受到此套接字的連接。
3public void setSoTimeout(int timeout) 通過指定超時值啟用/禁用 SO_TIMEOUT,以毫秒為單位。
4public void bind(SocketAddress host, int backlog) 將 ServerSocket 綁定到特定地址(IP 地址和端口號)。

六、Socket 類的方法

java.net.Socket 類代表客戶端和服務器都用來互相溝通的套接字。客戶端要獲取一個 Socket 對象通過實例化 ,而 服務器獲得一個 Socket 對象則通過 accept() 方法的返回值。

Socket 類有五個構造方法.

序號方法描述
1public Socket(String host, int port) throws UnknownHostException, IOException. 創建一個流套接字并將其連接到指定主機上的指定端口號。
2public Socket(InetAddress host, int port) throws IOException 創建一個流套接字并將其連接到指定 IP 地址的指定端口號。
3public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. 創建一個套接字并將其連接到指定遠程主機上的指定遠程端口。
4public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. 創建一個套接字并將其連接到指定遠程地址上的指定遠程端口。
5public Socket() 通過系統默認類型的 SocketImpl 創建未連接套接字

當 Socket 構造方法返回,并沒有簡單的實例化了一個 Socket 對象,它實際上會嘗試連接到指定的服務器和端口。

下面列出了一些感興趣的方法,注意客戶端和服務器端都有一個 Socket 對象,所以無論客戶端還是服務端都能夠調用這些方法。

序號方法描述
1public void connect(SocketAddress host, int timeout) throws IOException 將此套接字連接到服務器,并指定一個超時值。
2public InetAddress getInetAddress() 返回套接字連接的地址。
3public int getPort() 返回此套接字連接到的遠程端口。
4public int getLocalPort() 返回此套接字綁定到的本地端口。
5public SocketAddress getRemoteSocketAddress() 返回此套接字連接的端點的地址,如果未連接則返回 null。
6public InputStream getInputStream() throws IOException 返回此套接字的輸入流。
7public OutputStream getOutputStream() throws IOException 返回此套接字的輸出流。
8public void close() throws IOException 關閉此套接字。

例子(一):Socket 實例

1. 服務端

如下的 MySocketServer 是一個服務端程序,該程序通過 socket 連接到服務器并發送一個請求,然后等待一個響應。

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class MySocketServer extends Thread{private ServerSocket serverSocket;public MySocketServer(int port)throws IOException {//創建ServerSocket監聽端口portserverSocket = new ServerSocket(port);//設置等待時間:10000毫秒沒有監聽到Socket連接該端口就報錯serverSocket.setSoTimeout(10000);}public void run(){try{//ServerSocket等待連接,鏈接成功就創建一個與客戶端對等通信的socketSocket server = serverSocket.accept();System.out.println("客戶"+server.getLocalAddress()+"連接成功");//獲取Socket的輸入流輸出流DataInputStream inputStream = new DataInputStream(server.getInputStream());DataOutputStream outputStream = new DataOutputStream(server.getOutputStream());while(true){//從流中獲取信息String msg = inputStream.readUTF();//當客戶端傳遞的信息為ends時,結束。if(msg.equals("ends")) break;//服務端顯示流中的信息System.out.println(msg);}server.close();}catch(Exception ex){ex.printStackTrace();}}public static void main(String[] args){Scanner scanner = new Scanner(System.in);try{System.out.println("請輸入服務端綁定端口:");//運行線程讓服務端異步運行這樣可以讓主程序繼續干自己的事Thread t = new MySocketServer(scanner.nextInt());t.run();}catch(Exception ex){ex.printStackTrace();}}
}

2. 客戶端

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;public class MySocketClient{public static void main(String[] args){try{Scanner keyboard = new Scanner(System.in);System.out.println("請輸入連接主機的IP地址:");String host = keyboard.nextLine();System.out.println("輸入主機"+host+" 的端口號:");int port = keyboard.nextInt();//創建Socket并嘗試連接 IP=host && 端口=port的服務端Socket client = new Socket(host,port);InputStream in = client.getInputStream();OutputStream out = client.getOutputStream();DataInputStream inputStream = new DataInputStream(in);DataOutputStream outputStream = new DataOutputStream(out);while(true){String msg = keyboard.nextLine();outputStream.writeUTF(msg);//當輸入了ends時,客戶端關閉socket,服務端也關閉socket,二者結束通信。if(msg.equals("ends"))break;}client.close();}catch(Exception ex){ex.printStackTrace();};}
}

3. 測試結果

在這里插入圖片描述

例子(二):聊天室

1. 服務端

  • 服務端使用while循環的添加Socket用戶
  • 每個用戶有自己獨立的線程(異步性:使各個用戶可以同時輸出輸入的同時服務端能夠繼續監聽端口)

在這里插入圖片描述

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;public class ChatRoomServer{private static ServerSocket serverSocket;private static ArrayList<Socket> clientList = new ArrayList<Socket>();public static void main(String[] args){try{serverSocket = new ServerSocket(8888);while(true){Socket client = serverSocket.accept();clientList.add(client);//TODO:開啟客戶端線程,進行異步聊天ClientThread ct = new ClientThread(client,clientList);ct.start();}}catch(Exception ex){ex.printStackTrace();}finally {try{if(serverSocket != null)serverSocket.close();}catch(Exception ex){ex.printStackTrace();}}}
}class ClientThread extends Thread{private Socket client = null;private ArrayList<Socket> clientList;public ClientThread(Socket s,ArrayList<Socket>ss){client = s;clientList = ss;}public void run(){DataInputStream input = null;DataOutputStream output =  null;try{input = new DataInputStream(client.getInputStream());String rec = null;String send = null;while(true){if(!client.isClosed()){rec = input.readUTF();System.out.println("服務端接收到數據:"+rec);clientList.trimToSize();String[] param = rec.split("&");//將輸入進行一些封裝if("$start$".equals(param[1])){send = param[0] + "進入聊天室";}else{send = param[0] + "說:  " + param[1];}//將非取消信號的數據發送出去if(!("$ends$".equals(param[1]))){for(Socket socket : clientList){if(!socket.isClosed()){output = new DataOutputStream(socket.getOutputStream());output.writeUTF(send);}}}else{for(Socket socket : clientList){if(socket!= client && !socket.isClosed()){output = new DataOutputStream(socket.getOutputStream());output.writeUTF(param[0]+"已退出聊天室");}}output = new DataOutputStream(client.getOutputStream());output.writeUTF("$ends$");client.close();input.close();output.close();}}}}catch(Exception ex){ex.printStackTrace();}}
}

2. 客戶端

在這里插入圖片描述

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;public class ChatRoomClient {public static final String ip = "127.0.0.1";public static final int port = 8888;public Socket socket = null;public DataInputStream input = null;public DataOutputStream output = null;public Scanner keyboard = new Scanner(System.in);public String send;public String name;public void start(){try{System.out.println(" ################ 歡迎進入Socket聊天室 ################ ");System.out.println("輸入您在聊天室的昵稱: ");name = keyboard.nextLine();socket = new Socket(ip,port);input = new DataInputStream(socket.getInputStream());output = new DataOutputStream(socket.getOutputStream());send = name + "&$start$";System.out.println(" ################ 進入聊天室成功 ################ ");System.out.println("如需退出聊天室,輸入'$ends$'即可....");output.writeUTF(send);//TODO: 編寫聊天的線程MsgThread mt = new MsgThread(output,name,input);mt.start();while(true){String rec = input.readUTF();if("$ends$".equals(rec)){System.out.println(" ################ 退出聊天室成功 ################ ");input.close();output.close();socket.close();System.exit(0);}else{System.out.println(rec);}}}catch(Exception ex){ex.printStackTrace();}finally {try{if(socket!= null){socket.close();input.close();output.close();}}catch (Exception ex){ex.printStackTrace();}}}public static void main(String[] args){ChatRoomClient client = new ChatRoomClient();client.start();}
}
class MsgThread extends Thread{private DataInputStream input;private DataOutputStream output;private Scanner keyboard = new Scanner(System.in);public static String name;public MsgThread(DataOutputStream o,String n,DataInputStream i){output = o;input = i;name = n;}public void run(){ChatRoomClient client = new ChatRoomClient();try{while(true){String send = name+"&" + keyboard.nextLine();output.writeUTF(send);}}catch(Exception ex){ex.printStackTrace();}finally {System.out.println("sfef");}}
}

3. 測試結果

在這里插入圖片描述

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

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

相關文章

軟件測試之接口測試自動化(詳解版)

本著以和大家交流如何實現高效的接口測試為出發點&#xff0c;本文包含了我在接口測試領域的一些方法和心得&#xff0c;希望大家一起討論和分享&#xff0c;內容包括但不僅限于&#xff1a; 服務端接口測試介紹接口測試自動化介紹接口測試自動化實踐關于接口測試自動化的思考…

質量工程化,交付快速化

質量和速度之間權衡讓人很難取舍&#xff0c;而通過推進質量工程&#xff0c;以系統化的方式識別和優化系統痛點&#xff0c;可以幫助團隊構建既快又好的精益軟件生產系統。原文: Quality Engineered, Speed Delivered 所有人都想要更快的速度。 但需要解決復雜問題: 權衡質量會…

Kotlin(十四) 擴展函數和運算符重載

目錄 擴展函數 語法結構 代碼示例 運算符重載 語法結構 一元操作符 二元操作符 數值類型操作符 等于和不等于操作符 比較操作符 調用操作符 擴展函數 語法結構 對于擴張函數的語法結構其實很簡單&#xff0c;你想在那個類中添加擴張函數&#xff0c;那么你就用該類…

6. Zigzag Conversion

按照下標找規律注意leetcode的運行輸出&#xff0c;如果其中一組用例出現死循環&#xff0c;輸出結果會在一個文件&#xff0c;即部分測試用例正確&#xff0c;部分錯誤且出現死循環&#xff0c;則需辨別輸出結果屬于哪一份測試用例 class Solution { public:string convert(s…

(二)五種最新算法(SWO、COA、LSO、GRO、LO)求解無人機路徑規劃MATLAB

一、五種算法&#xff08;SWO、COA、LSO、GRO、LO&#xff09;簡介 1、蜘蛛蜂優化算法SWO 蜘蛛蜂優化算法&#xff08;Spider wasp optimizer&#xff0c;SWO&#xff09;由Mohamed Abdel-Basset等人于2023年提出&#xff0c;該算法模型雌性蜘蛛蜂的狩獵、筑巢和交配行為&…

w3school學習筆記3(NumPy)

系列文章目錄 文章目錄 系列文章目錄前言一、NumPy簡介二、NumPy入門三、NumPy創建四、NumPy數組索引五、NumPy數組裁切六、NumPy數據類型七、NumPy副本/視圖八、NumPy數據形狀九、NumPy數組重塑十、NumPy數組迭代總結 前言 一、NumPy簡介 1、什么是Numpy&#xff1f; NumPy是…

線上盲盒小程序,開啟互聯網盲盒時代

近年來&#xff0c;盲盒經濟在國內非常火爆&#xff0c;各類盲盒品牌層出不窮&#xff0c;深受國內外年輕人、消費者的喜愛。 目前&#xff0c;根據數據顯示&#xff0c;盲盒市場不僅在線下異常火熱&#xff0c;線上盲盒也是成為了大眾的新選擇。各類電商平臺中盲盒的成交額更…

Esxi7Esxi8設置VMFSL虛擬閃存的大小

Esxi7Esxi8設置VMFSL虛擬閃存的大小 ESXi7,8 默認安裝會分配一個 VMFSL(VMFS-L)(Local VMFS)很大空間(120G), 感覺很浪費, 實際給 8G 就可以了, 最少 6G , 經實驗,給2G沒法安裝 . Esxi7是虛擬閃存的 修改的方法是: 在安裝時修改 設置 autoPartitionOSDataSize8192 在cdromBoo…

快捷切換raw頁面到repo頁面-Raw2Repo插件

Raw2Repo By Rick &#x1f4d6;快捷切換代碼托管平臺raw頁面到repo頁面 &#x1f517;github鏈接 https://github.com/rickhqh/Raw2Repo ?Features 功能&#xff1a; ?單擊 Raw2Repo 插件按鈕&#xff0c;即可跳轉到相應的代碼倉庫頁面。?支持 GitHub、Gitee、GitCode …

spring boot整合mybatis進行部門管理管理的增刪改查

部門列表查詢&#xff1a; 功能實現&#xff1a; 需求&#xff1a;查詢數據庫表中的所有部門數據&#xff0c;展示在頁面上。 準備工作&#xff1a; 準備數據庫表dept&#xff08;部門表&#xff09;&#xff0c;實體類Dept。在項目中引入mybatis的起步依賴&#xff0c;mysql的…

【ET8】1.ET8入門-運行指南

主要學習網址 論壇地址為&#xff1a;https://et-framework.cn Git地址為&#xff1a;GitHub - egametang/ET: Unity3D Client And C# Server Framework 官方QQ群 : 474643097 項目檢出 檢出項目切換到release8.0分支 GitHub地址&#xff1a;GitHub - egametang/ET: Unity…

[足式機器人]Part2 Dr. CAN學習筆記-數學基礎Ch0-5Laplace Transform of Convolution卷積的拉普拉斯變換

本文僅供學習使用 本文參考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN學習筆記-數學基礎Ch0-5Laplace Transform of Convolution卷積的拉普拉斯變換 Laplace Transform : X ( s ) L [ x ( t ) ] ∫ 0 ∞ x ( t ) e ? s t d t X\left( s \right) \mathcal{L} \left[ x\lef…

基于Swin_Transformer的圖像超分辨率系統

1.研究背景與意義 項目參考AAAI Association for the Advancement of Artificial Intelligence 研究背景與意義 隨著科技的不斷發展&#xff0c;圖像超分辨率技術在計算機視覺領域中變得越來越重要。圖像超分辨率是指通過使用計算機算法將低分辨率圖像轉換為高分辨率圖像的過…

AI:91-基于深度學習的手寫數學表達式識別

?? 本文選自專欄:人工智能領域200例教程專欄 從基礎到實踐,深入學習。無論你是初學者還是經驗豐富的老手,對于本專欄案例和項目實踐都有參考學習意義。 ??? 每一個案例都附帶有在本地跑過的核心代碼,詳細講解供大家學習,希望可以幫到大家。歡迎訂閱支持,正在不斷更新…

51單片機的時鐘電路與時序以及 復位電路和電源模式

51單片機的時鐘電路與時序以及 復位電路和電源模式 本文主要涉及51單片機的時鐘電路以及相關時序的知識&#xff0c;也講解了了51單片機的復位電路以及電源模式。 文章目錄 51單片機的時鐘電路與時序以及 復位電路和電源模式一、時鐘電路與時序1、 時鐘電路設計1.1 內部時鐘方式…

用stl寫一個自動打分比賽的案例

我們要實現六名選手進行隨機平均分為兩組&#xff0c;先分別淘汰兩組中的最后一名&#xff0c; 再決出第一名。 抽象選手 class player { public:string name;int score; }; 一個選手有名字和分數 首先我們需要vector容器保存選手的編號&#xff0c;便于后續的操作。 再用…

導入PR的視頻畫面是黑屏的怎么辦?

在現代視頻編輯領域中&#xff0c;越來越多的人使用Adobe Premiere Pro來編輯和制作視頻&#xff0c;但是在某些情況下&#xff0c;用戶可能需要透明背景的視頻進行創作&#xff0c;那么如何創作透明背景的視頻呢&#xff1f; 要制作具有透明背景的視頻&#xff0c;我們需要使…

如何贏得并留住訂閱者:12 個必須嘗試的訂閱營銷策略

Netflix、Hubspot、Spotify 和 Slack 都是流行的基于訂閱的服務&#xff0c;您可能每天都會使用它們&#xff0c;無論是工作還是娛樂。這些例子表明&#xff0c;訂閱業務模式深受 SaaS 創業者的青睞。 這種模式的吸引力很容易理解&#xff0c;特別是考慮到訂閱市場預計到 2025…

C //例10.5 有一個磁盤文件,內有一些信息。要求第1次將它的內容顯示在屏幕上,第2次把它復制到另一文件上。

C程序設計 &#xff08;第四版&#xff09; 譚浩強 例10.5 例10.5 有一個磁盤文件&#xff0c;內有一些信息。要求第1次將它的內容顯示在屏幕上&#xff0c;第2次把它復制到另一文件上。 IDE工具&#xff1a;VS2010 Note: 使用不同的IDE工具可能有部分差異。 代碼塊 方法&a…

mysql支持的整數類型、各類型整數能夠表示的數值范圍

MySQL :: MySQL 8.2 Reference Manual :: 11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT mysql支持的整數有&#xff1a;TINYINT、SMALLINT、MEDIUMINT、INT&#xff08;INT和INTEGER是同義詞&#xff09;、BIGINT&#xff0c;各…