日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

在Java中使用Socket模拟客户端和服务端(多线程)

發(fā)布時間:2025/5/22 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Java中使用Socket模拟客户端和服务端(多线程) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1:Socket與ServerSocket的交互

2.Socket和ServerSocket介紹

Socket

構造函數(shù)

Socket()

Socket(InetAddress address, int port)throws UnknownHostException, IOException

Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException

Socket(String host, int port)throws UnknownHostException, IOException(最簡單的連接方式)

Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException

除去第一種不帶參數(shù)的之外,其它構造函數(shù)會嘗試建立與服務器的連接。如果失敗會拋出IOException錯誤。如果成功,則返回Socket對象。

InetAddress是一個用于記錄主機的類,其靜態(tài)getHostByName(String msg)可以返回一個實例,其靜態(tài)方法getLocalHost()也可以獲得當前主機的IP地址,并返回一個實例。

Socket(String host, int port, InetAddress localAddress, int localPort)構造函數(shù)的參數(shù)分別為目標IP、目標端口、綁定本地IP、綁定本地端口。

Socket方法

getInetAddress();??? 遠程服務端的IP地址

getPort();??? 遠程服務端的端口

getLocalAddress()??? 本地客戶端的IP地址

getLocalPort()??? 本地客戶端的端口

getInputStream();??? 獲得輸入流

getOutStream();??? 獲得輸出流

值得注意的是,在這些方法里面,最重要的就是getInputStream()和getOutputStream()了。

Socket狀態(tài)

isClosed();???? //連接是否已關閉,若關閉,返回true;否則返回false

isConnect();      //如果曾經(jīng)連接過,返回true;否則返回false

isBound();???? //如果Socket已經(jīng)與本地一個端口綁定,返回true;否則返回false

ServerSocket

構造函數(shù)

ServerSocket()throws IOException

ServerSocket(int port)throws IOException

ServerSocket(int port, int backlog)throws IOException

ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException

注意點:

1. port服務端要監(jiān)聽的端口;backlog客戶端連接請求的隊列長度;bindAddr服務端綁定IP

2. 如果端口被占用或者沒有權限使用某些端口會拋出BindException錯誤。譬如1~1023的端口需要管理員才擁有權限綁定。

3. 如果設置端口為0,則系統(tǒng)會自動為其分配一個端口;

4. bindAddr用于綁定服務器IP,為什么會有這樣的設置呢,譬如有些機器有多個網(wǎng)卡。

5. ServerSocket一旦綁定了監(jiān)聽端口,就無法更改。ServerSocket()可以實現(xiàn)在綁定端口前設置其他的參數(shù)。

3.實例前說明

Socket網(wǎng)絡編程主要用于兩臺機器之間的數(shù)據(jù)傳輸,大致過程為:建立連接→信息傳遞→關閉連接。我們可以理解為服務器(ServerSocket)和客戶端(Socket),服務器提供連接服務,客戶端鏈接服務器。因為服務器需要向多臺客戶端提供服務,所以需要一直保持監(jiān)聽狀態(tài),不斷地監(jiān)聽客戶端請求,在這個過程中,ServerSocket一直處于阻斷狀態(tài),直到有客戶端連接,馬上返回一個Socket對象,然后通過IO流傳輸數(shù)據(jù),在這個過程中,當有數(shù)據(jù)傳輸?shù)臅r候,IO流才被激活,其余時間都處于阻斷狀態(tài),等待數(shù)據(jù)發(fā)送過來,然后進行處理。

注意:

當我們發(fā)送數(shù)據(jù)的時候,必須使用flush()方法,將數(shù)據(jù)提交,否則只會存在于緩沖中,不會發(fā)送數(shù)據(jù),有時候即使我們使用flush()方法,也無法從另一臺電腦上讀取到數(shù)據(jù),這是因為Socket會將數(shù)據(jù)先存儲起來,等到數(shù)據(jù)量達到一定大小的時候,會一起提交(或者這樣理解,flush()會根據(jù)換行符’\n’判斷用戶是否完成輸入,如果沒有看到’\n’,Socket認為用戶數(shù)據(jù)還沒有寫完,仍在保留在緩存池中)所以我們可以在要提交的數(shù)據(jù)加上’\n’強制提交就可以了。

不過,如果我們沒必要很多的交互,只需要交互一次就可以了,就可以不在乎這些,當關閉Socket的輸入輸出流的時候,Socket會將緩存池中的數(shù)據(jù)全部提交到另一臺機器。

最后最重要的,當我們用完流的時候,一定要及時關閉,養(yǎng)成良好的習慣。

在下面的實例中,我通過多線程的方式保證服務器和客戶端一直處于數(shù)據(jù)交互狀態(tài),并且使用線程池的方式維護線程。、

線程類:

package com.best.alivn.socketservice; import java.io.*; import java.net.Socket; import java.util.Scanner;/**讓服務器處理與客戶端通訊放在線程中* Created by Alivn on 2017/3/18.*/ public class SessionThread implements Runnable{private final Socket client;private static Integer Tag=0;public SessionThread(Socket client) {this.client = client;}@Overridepublic void run() {//輸出流PrintWriter writer=null;//獲取客戶端輸入流,得到客戶端發(fā)來的消息try {//讀取客戶端的數(shù)據(jù)//讀取到的一行數(shù)據(jù)String line=null;//客戶端發(fā)來的數(shù)據(jù)//開啟一個讀線程Thread write_thread= new Thread(new Runnable() {@Overridepublic void run() {//輸入流InputStream inputStream=null;BufferedReader reader=null;try {while (true) {inputStream= client.getInputStream();//為了提高效率,轉換成字符流reader=new BufferedReader(new InputStreamReader(inputStream));String line=null;while ((line=reader.readLine())!=null){System.out.println(line);}}} catch (IOException e) {//流異常 e.printStackTrace();}finally {//關閉流try {inputStream.close();reader.close();} catch (IOException e) {e.printStackTrace();}}}});write_thread.start();//獲取輸出流,往客戶端發(fā)送數(shù)據(jù)writer=new PrintWriter(client.getOutputStream());//客戶端剛連接的時候,客戶端反饋信息String send_msg ="您已成功連接到服務器......--[Server]";writer.println(send_msg);writer.flush();//可以多次發(fā)送//從鍵盤輸入while ("1".equals("1")) {Scanner scanner=new Scanner(System.in);send_msg =scanner.nextLine()+"--[Server]";writer.println(send_msg);//注意(我們發(fā)送數(shù)據(jù)的時候,flush方法會提交我們的數(shù)據(jù),但是還不會發(fā)送,當數(shù)據(jù)達到一定容量才會發(fā)送,// 或者讀到換行符的時候發(fā)送) writer.flush();}} catch (IOException e) {//獲取客戶端輸入流失敗 e.printStackTrace();}finally {//關閉流try {client.shutdownInput();client.shutdownOutput();writer.close();} catch (IOException e) {//關閉輸入輸出流失敗 e.printStackTrace();}}} }

服務器類:

package com.best.alivn.socketservice; import scala.actors.threadpool.ExecutorService; import scala.actors.threadpool.Executors; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;/**服務器* Created by Alivn on 2017/3/18.*/ public class Server {//甚至端口號private final static Integer PORT=8888;//設置開啟的線程數(shù)private final static Integer THREAD_SIZE=5;//創(chuàng)建線程池private static ExecutorService executorService=null;public static void main(String[]args){executorService = Executors.newFixedThreadPool(THREAD_SIZE);//創(chuàng)建服務器套接字try {//創(chuàng)建三個線程放入到線程池中....ServerSocket serverSocket=new ServerSocket(PORT);//開啟服務器,一直處于監(jiān)聽的狀態(tài)System.out.println("[Server]:服務器已啟動.........");while (true){//服務器根據(jù)端口號,監(jiān)聽客戶端鏈接,Socket client = serverSocket.accept();System.out.println("[Server]:有客戶端鏈接至服務器.......");//將交互放到線程中SessionThread session=new SessionThread(client);//放入到線程池中 session.run();executorService.execute(session);}} catch (IOException e) {//實例化服務器失敗 e.printStackTrace();}}}客戶端類: package com.best.alivn.socketservice; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner;/**客戶端* Created by Alivn on 2017/3/18.*/ public class Client {private final static String host="localhost";private final static Integer port=8888;public static void main(String[] args) {Socket socket=null;//輸入流BufferedReader reader=null;//創(chuàng)建客戶端對象try {//連接服務器socket=new Socket(host,port);//客戶端剛連接的時候,客戶端反饋信息//輸出流final PrintWriter writer=new PrintWriter(socket.getOutputStream());;String send_msg ="你好,我是小白......--[Client]";writer.println(send_msg);writer.flush();//開啟一個線程,處理循環(huán)Thread write_Stream= new Thread(new Runnable() {@Overridepublic void run() {//循環(huán)輸入數(shù)據(jù)Scanner scanner=new Scanner(System.in);while ("1".equals("1")){String send_msg=scanner.nextLine()+"--[Client]";writer.println(send_msg);writer.flush();}}});write_Stream.start();while ("1".equals("1")) {//獲取輸入流,得服務端的數(shù)據(jù)reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));String line=null;while ((line=reader.readLine())!=null){System.out.println(line);}}writer.close();} catch (IOException e) {//鏈接失敗 文件讀取失敗 e.printStackTrace();}finally {//關閉流try {reader.close();socket.shutdownInput();socket.shutdownOutput();} catch (IOException e) {e.printStackTrace();}}} }

轉載于:https://www.cnblogs.com/ljp-sun/p/6576720.html

總結

以上是生活随笔為你收集整理的在Java中使用Socket模拟客户端和服务端(多线程)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。