最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Socket通信介紹及可能遇到的問題解決

 更新時(shí)間:2017年10月11日 09:56:13   作者:搖頭耶穌  
最近在學(xué)習(xí)Java中的Socket通信,所以下面這篇文章主要給大家介紹了關(guān)于Java Socket通信介紹及可能遇到問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起看看吧。

前言

本文主要給大家介紹了關(guān)于Java中Socket通信的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。

Java中基于TCP協(xié)議實(shí)現(xiàn)網(wǎng)絡(luò)通信的兩個(gè)類:客戶端的Socket和服務(wù)器端的ServerSocket。

Socket通信模型如圖所示:

不管Socket通信的功能有多復(fù)雜,任何socket通信過程的基本結(jié)構(gòu)都是一樣的。

其基本步驟為:

      ①分別在客戶端和服務(wù)器端創(chuàng)建Socket和ServerSocket實(shí)例;服務(wù)器端通過.accept()方法等待請(qǐng)求并阻塞。請(qǐng)求收到后,建立連接Socket對(duì)象。

      ②通過getInputStream和getOutputStream方法分別在客戶端和服務(wù)器端打開輸入輸出流

      ③利用IO流進(jìn)行讀寫操作

      ④關(guān)閉所有的流資源和套接字資源。

其中,編程工作主要集中在第三步,其他的部分代碼基本相同。所有步驟都可能拋出IO異常!

我在編寫一個(gè)簡(jiǎn)單的socket程序時(shí),使用的Socket通信出現(xiàn)了一個(gè)問題:我在客戶端寫入的數(shù)據(jù),在服務(wù)器端無法輸出。當(dāng)我從客戶端斷開連接時(shí),之前寫入的所有數(shù)據(jù)立刻在服務(wù)器端輸出出來了。經(jīng)過反復(fù)的驗(yàn)證和求解,以下是我的結(jié)論和解決方法。希望有同樣問題的小伙伴看完可以解決問題。

通過一端的Socket建立了PrintWriter類來寫入數(shù)據(jù),通過另一端的Socket建立了BufferedReader類來讀取數(shù)據(jù)并輸出。

如果數(shù)據(jù)寫入后沒有被顯示,可能的原因有兩種:

一、寫入的數(shù)據(jù)存儲(chǔ)在緩沖區(qū)中,沒有被寫入IO流中:

如果不主動(dòng)的干涉,寫入的數(shù)據(jù)會(huì)一直堆在緩沖區(qū)中,直到緩沖區(qū)滿了引發(fā)JVM自動(dòng)刷新緩沖區(qū)。顯然這不符合我們的需求。對(duì)于這種情況,PrintWriter類提供了flush()方法來強(qiáng)制刷新緩沖區(qū),將緩沖區(qū)數(shù)據(jù)寫入IO流中。另外,PrintWriter類的構(gòu)造器有一個(gè)參數(shù)”boolean autoflush“,這個(gè)參數(shù)默認(rèn)為false,如果設(shè)置為true,則會(huì)開啟自動(dòng)刷新緩沖區(qū)功能。但是請(qǐng)注意,這里的自動(dòng)刷新是有觸發(fā)條件的,那就是:PrintWriter類寫入數(shù)據(jù)的方法必須是println、printf或者format方法時(shí),才會(huì)觸發(fā)自動(dòng)刷新。如果是調(diào)用write()這類方法寫入數(shù)據(jù),是不會(huì)觸發(fā)自動(dòng)刷新的!總結(jié)起來,就是三點(diǎn):autoflush參數(shù)設(shè)置,write和println方法的選擇,flush方法的使用。對(duì)這三個(gè)進(jìn)行組合,就能保證在Socket通信的某一端寫入數(shù)據(jù)時(shí),數(shù)據(jù)一定能成功地寫入到IO流中!

二、讀取數(shù)據(jù)使用了readLine()方法,該方法沒有正常的結(jié)束:

請(qǐng)注意,BufferedReader類的readLine()方法是一個(gè)阻塞函數(shù)!也就是說,這個(gè)方法本身是讀取一行數(shù)據(jù),但是它自己識(shí)別不了什么叫做“一行”!當(dāng)調(diào)用該方法讀取完一段數(shù)據(jù)后,它會(huì)阻塞,而不會(huì)return它的讀取數(shù)據(jù)。這就是為什么有的時(shí)候明明已經(jīng)刷新了緩沖區(qū)正確的寫入數(shù)據(jù)了,還是通過輸入流讀取數(shù)據(jù)并顯示出來的原因。

對(duì)于readLine()方法,它解除阻塞、正確結(jié)束并返回讀取的值,只有以下幾種情況:

      ①讀取的數(shù)據(jù)里含有回車符"\r"或者換行符"\n"或者回車換行符"\r\n";

      ②讀取的數(shù)據(jù)是在另一端通過println方法寫入的,因?yàn)閜rintln方法自帶換行符;

      ③BufferedReader類的緩沖區(qū)滿了,那么JVM會(huì)自動(dòng)刷新緩沖區(qū)從而釋放“積攢”的數(shù)據(jù)(但是鑒于默認(rèn)緩沖區(qū)大小為8192個(gè)字符,對(duì)于小數(shù)據(jù)量的通信,顯然觸發(fā)不了);

      ④對(duì)于讀取的數(shù)據(jù),寫入這些數(shù)據(jù)的流發(fā)生異?;蛘咧苯雨P(guān)閉,那么readLine()就會(huì)把它吃的數(shù)據(jù)全部吐出來。這就剛好解釋了,為什么在我的程序中,斷開客戶端Socket連接,服務(wù)器端立刻輸出所有客戶端消息的原因。

綜上,在Socket通信過程中,保證某一端輸出流的緩沖被刷新,保證另一端的readLine方法能正常停止,即可解決寫入的數(shù)據(jù)在另一端無法輸出的問題。

以下是我修改后能成功運(yùn)行的代碼,分別是服務(wù)器端Socket和客戶端Socket。

over!

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
public class ShakingServer{
 public static void main(String[] args) throws IOException {

 //創(chuàng)建服務(wù)器套接字實(shí)例,設(shè)置監(jiān)聽端口為2000
 ServerSocket server=new ServerSocket(2000);
 //開始監(jiān)聽客戶端的請(qǐng)求,并阻塞
 Socket socket=server.accept();
 //請(qǐng)求收到后,自動(dòng)建立連接。通過IO流進(jìn)行數(shù)據(jù)傳輸
 System.out.println("連接建立成功");

 OutputStream os=socket.getOutputStream();
 PrintWriter pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(os)),true);
 pw.write("歡迎訪問搖頭耶穌的世界!");
 pw.flush();
  //因?yàn)槲谊P(guān)閉了輸出流,所以另一端的readLine方法才正常結(jié)束了
 socket.shutdownOutput();

 InputStream is=socket.getInputStream();
 InputStreamReader isr=new InputStreamReader(is);
 BufferedReader br=new BufferedReader(isr);
 while(true) {
  String str=br.readLine();
  if(str.equals("quit")) {
  break;
  }
  System.out.println("Client said: "+str);
 }
 socket.shutdownInput();
 //socket.shutdownOutput();
 socket.close();
 server.close();
 }
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

public class ShakingClient{
 public static void main(String[] args) throws IOException{

 //創(chuàng)建客戶端的套接字,設(shè)置連接的服務(wù)器的IP地址和端口號(hào)
 Socket socket=new Socket("169.254.132.203",2000);
 //輸入流讀取服務(wù)器發(fā)送的信息
 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
  //開啟自動(dòng)刷新緩沖區(qū)
 PrintWriter pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);  
  //從鍵盤讀取數(shù)據(jù)
 BufferedReader ii=new BufferedReader(new InputStreamReader(System.in));
 System.out.println(br.readLine());
  //因?yàn)殚_啟了自動(dòng)刷新,且調(diào)用的是println方法,所以可以不調(diào)用flush方法
 pw.println("請(qǐng)求進(jìn)入搖頭耶穌的世界");
 //pw.flush();
 while(true) {
  String str=ii.readLine();
  //使用了回車符來保證另一端的readLine方法正常結(jié)束
  pw.write(str+"\r");
  pw.flush();
  //如果輸入quit則退出聊天室
  if(str.equals("quit")) {
  break;
  }
 }
 socket.shutdownInput();
 socket.shutdownOutput();
 socket.close();
 }
}

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • java+opencv實(shí)現(xiàn)人臉識(shí)別功能

    java+opencv實(shí)現(xiàn)人臉識(shí)別功能

    這篇文章主要介紹了java+opencv實(shí)現(xiàn)人臉識(shí)別功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • Java中的Enum枚舉使用方法解析

    Java中的Enum枚舉使用方法解析

    這篇文章主要介紹了Java中的Enum枚舉使用方法解析,枚舉是一種數(shù)據(jù)類型,和int、double、string等類型相似,枚舉用于聲明一組命名的常數(shù),當(dāng)一個(gè)變量有幾種可能的取值時(shí),可以將它定義為枚舉類型,需要的朋友可以參考下
    2023-11-11
  • Java工程使用ffmpeg進(jìn)行音視頻格式轉(zhuǎn)換的實(shí)現(xiàn)

    Java工程使用ffmpeg進(jìn)行音視頻格式轉(zhuǎn)換的實(shí)現(xiàn)

    FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計(jì)算機(jī)程序,本文主要介紹了Java工程使用ffmpeg進(jìn)行音視頻格式轉(zhuǎn)換的實(shí)現(xiàn)
    2024-02-02
  • Java如何通過"枚舉的枚舉"表示二級(jí)分類的業(yè)務(wù)場(chǎng)景

    Java如何通過"枚舉的枚舉"表示二級(jí)分類的業(yè)務(wù)場(chǎng)景

    這篇文章主要介紹了Java如何通過"枚舉的枚舉"表示二級(jí)分類的業(yè)務(wù)場(chǎng)景問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • WebClient拋UnsupportedMediaTypeException異常解決

    WebClient拋UnsupportedMediaTypeException異常解決

    這篇文章主要為大家介紹了WebClient拋UnsupportedMediaTypeException異常的解決方案,文中給大家介紹了六中方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • Java 中的 @SneakyThrows 注解的使用方法(簡(jiǎn)化異常處理的利與弊)

    Java 中的 @SneakyThrows 注解的使用方法(簡(jiǎn)化異常處理的利與弊)

    @SneakyThrows是Lombok提供的一個(gè)注解,用于簡(jiǎn)化Java方法中的異常處理,特別是對(duì)于檢查型異常,它允許方法拋出異常而不必顯式聲明或捕獲這些異常,本文介紹Java 中的 @SneakyThrows 注解的使用方法,感興趣的朋友一起看看吧
    2025-03-03
  • java簡(jiǎn)單實(shí)現(xiàn)自定義日歷

    java簡(jiǎn)單實(shí)現(xiàn)自定義日歷

    這篇文章主要為大家詳細(xì)介紹了java簡(jiǎn)單實(shí)現(xiàn)自定義日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Java中classpath的基本概念和配置方法詳析

    Java中classpath的基本概念和配置方法詳析

    這篇文章主要介紹了Java中的classpath概念,包括其基本概念、設(shè)置方法以及在Java應(yīng)用中的作用,在IDE中的配置也進(jìn)行了詳細(xì)說明,并提到了一些通用注意事項(xiàng),需要的朋友可以參考下
    2025-02-02
  • Java中常用文本加解密工具類總結(jié)

    Java中常用文本加解密工具類總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Java中常用的幾種文本加解密工具類,包括AES對(duì)稱加密、RSA非對(duì)稱加密、哈希算法加密和Base64編解碼,需要的可以參考下
    2024-11-11
  • 基于@PostConstruct注解的使用,解決向靜態(tài)變量注入值

    基于@PostConstruct注解的使用,解決向靜態(tài)變量注入值

    這篇文章主要介紹了基于@PostConstruct注解的使用,解決向靜態(tài)變量注入值問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評(píng)論

九龙县| 泸溪县| 调兵山市| 玉田县| 崇州市| 龙山县| 巴林左旗| 南部县| 剑阁县| 梅河口市| 尖扎县| 惠安县| 乌鲁木齐县| 尖扎县| 明星| 平原县| 应用必备| 海宁市| 临桂县| 泽州县| 荃湾区| 葫芦岛市| 资源县| 札达县| 大城县| 同仁县| 璧山县| 杭州市| 辽源市| 江达县| 丰城市| 洛川县| 当阳市| 宽城| 年辖:市辖区| 临澧县| 阳新县| 鄂托克前旗| 沂源县| 内乡县| 沁阳市|