激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

香港云服务器
服務器之家 - 編程語言 - Java教程 - Java Socket上的Read操作阻塞問題詳解

Java Socket上的Read操作阻塞問題詳解

2022-03-02 12:52fw0124 Java教程

這篇文章主要介紹了Java Socket上的Read操作阻塞問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Socket上的Read操作阻塞問題

從Socket上讀取對端發過來的數據一般有兩種方法

1)按照字節流讀取

      BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
      int r = -1;
      List<Byte> l = new LinkedList<Byte>();
      while ((r = in.read()) != -1) {
          l.add(Byte.valueOf((byte) r));
      }

2)按照字符流讀取

      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));        
      String s;
      while ((s = in.readLine()) != null) {
          System.out.println("Reveived: " + s);
      }

這兩個方法read()和readLine()都會讀取對端發送過來的數據,如果無數據可讀,就會阻塞直到有數據可讀。或者到達流的末尾,這個時候分別返回-1和null。

這個特性使得編程非常方便也很高效。

但是這樣也有一個問題,就是如何讓程序從這兩個方法的阻塞調用中返回。

總結一下,有這么幾個方法

1)發送完后調用Socket的shutdownOutput()方法關閉輸出流,這樣對端的輸入流上的read操作就會返回-1。

注意不能調用socket.getInputStream().close()。這樣會導致socket被關閉。

當然如果不需要繼續在socket上進行讀操作,也可以直接關閉socket。

但是這個方法不能用于通信雙方需要多次交互的情況。

2)發送數據時,約定數據的首部固定字節數為數據長度。這樣讀取到這個長度的數據后,就不繼續調用read方法。

3)為了防止read操作造成程序永久掛起,還可以給socket設置超時。

如果read()方法在設置時間內沒有讀取到數據,就會拋出一個java.net.SocketTimeoutException異常。

例如下面的方法設定超時3秒。

socket.setSoTimeout(3000);

 

Socket編程---read方法阻塞問題

java通信項目簡單寫了個聊天室,實現群聊私聊了,就大言不慚地往簡歷上寫了對java網絡編程和多線程有了一定的了解。給客戶端各自開了線程,寫了句server.accept()、Socket client=new Socket("127.0.0.1",9999),就叫了解了? Too young too simple.

然而一問,BIO和NIO有什么區別?--- 納尼?什么玩意兒?

  • 那你說說你那個聊天室的流? --- 臥槽,這有什么好說的,get啊,輸入流用來讀的,輸出流用來寫數據給對方的
  • 可能知道我沒get到點吧,那你自己說一下你的通信項目吧 --- 哈哈,先創建一個ServerSocket對象,然后accept等客戶端來連,給每個客戶端都開一個線程各自處理
  • 奧,你是給每個客戶端都開了一個線程啊============ 結束會話

聊完了啊,可是我并不知道發生了什么,這特么到底要問啥啊。現在一想,可能對方覺得我特么就是傻缺吧,一個只會碼而沒有思想的人。

那不管,先不說BIO和NIO,通過這個,我倒是好像get到他是不是在跟我說流的阻塞問題。那么,總結一下吧。

講文件流的時候,我們會看到這兩個read方法,看一下API

Java Socket上的Read操作阻塞問題詳解

如果只是使用一次,那么沒有數據讀的時候,會一直阻塞,然后想執行下面那是不可能的了,直到有數據可讀;

如果用在while里,那么沒讀到文件末尾,也是一直阻塞的,直到被返回-1。

文件它是自己知道讀到文件末尾了,那么我們的Socket是兩端的通信,一直等待著對方傳來數據的,并不知道啥時候會完,所以就會一直不會等于-1,阻塞在while循環里了,下面的代碼就不會被執行。

package SocketIO; 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server { 
	public static void main(String[] args) throws IOException {
		String m = "";
		ServerSocket ss =  new ServerSocket(9999);
		Socket s = ss.accept();
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"...connected...");
		m = ip+"...connected...";
		InputStream in = s.getInputStream();
		int len = 0;
		byte[] buf = new byte[1024];
		while((len=in.read(buf))!=-1){
			m += new String(buf);
		}
		System.out.println(m);
		
		OutputStream out = s.getOutputStream();
		out.write("飯菜馬上到".getBytes());
		out.flush();
		in.close();
		out.close();
		s.close();
		ss.close();
	}
}
package SocketIO; 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException; 
public class Client {

	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("127.0.0.1", 9999);
		OutputStream out = s.getOutputStream();
		out.write("我肚子餓了".getBytes());
		out.flush();
		String m = "";
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = 0;
		while((len=in.read(buf))!=-1){
			m += new String(buf);
		}
		System.out.println(m);
		in.close();
		out.close();
		s.close();
	} 
}

當客戶端連接上服務器時,把“我肚子餓了”寫給服務器,服務器讀的時候不知道客戶端發沒發完,就一直阻塞在while循環里,故服務器的console只會輸出

Java Socket上的Read操作阻塞問題詳解,

而客戶端的console什么也不會輸出

那么,我們只用加一句,

Java Socket上的Read操作阻塞問題詳解

客戶端寫完數據后,就直接把輸出流shutdown,那么服務器讀到的就會是-1,跳出循環,繼續往下執行。那為什么服務器寫完數據后不把輸出流shutdown,你沒看見所有的流都close了嗎?客戶端當然會讀到-1,進而輸出我們想看到的東東了。如果你還不服,你把close都注釋掉,看看效果(都注釋掉了客戶端讀的時候又阻塞了),再加上s.shutdownOutput()再看看效果(這會又恢復正常了)。

Java Socket上的Read操作阻塞問題詳解Java Socket上的Read操作阻塞問題詳解

這個例子其實只是想說明socket編程中流的read方法是阻塞的。

那么,回到我們的聊天室來,我一個服務器要處理這么多個客戶端,如果一個客戶端的read方法阻塞了,那別的客戶端不都得等著它嗎?顯然,這是不可能的。那,一個客戶端給一個線程吧,讓它們自己阻塞自己的。

對于服務器端而言,給每個客戶端啟動一個線程,然后在每個客戶端各自的線程里循環去讀客戶端發來的數據,沒的話阻塞等待直到有,有的話轉發,所以阻塞在循環里也無所謂,反正while循環之外我暫時也沒想著執行。當然,還是要把它結束掉。

Java Socket上的Read操作阻塞問題詳解

對于服務器端,先讀后轉發,嵌在一個循環里,不會有什么問題。

而對于客戶端而言,我要隨時監聽去讀,又想著隨時去寫。那寫的操作不能在讀的循環里了啊,只能寫在外面。而讀的操作又是一直阻塞著的,豈會讓出時間讓你寫?那,大招來了。你把讀的操作放一個線程里不就得了,由它去阻塞,想怎么讀就怎么讀。那互不影響的話,我也想怎么寫就怎么寫啊。

Java Socket上的Read操作阻塞問題詳解

寫的操作我就不截圖了,就是在主線程里完成的。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/fw0124/article/details/41227543

延伸 · 閱讀

精彩推薦
1293
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 99精品视频网站 | 狠狠操视频网站 | 国产精品一区自拍 | 免费在线观看亚洲 | 黑人一区 | 国产91中文字幕 | 日本一区二区三区四区高清视频 | 亚洲成人黄色片 | 国产日韩一区二区三区在线观看 | 超碰97最新 | 色偷偷一区 | 亚洲性生活视频 | 精品国产91久久久久 | 黄色片网站在线播放 | chinese hd xxxx tube | 狠狠久久伊人中文字幕 | 亚洲日本韩国在线观看 | 91久久精品一区二区 | 久久人人爽人人爽人人片av免费 | 中国女警察一级毛片视频 | 亚洲精品欧美二区三区中文字幕 | 羞羞视频免费观看入口 | 精品国产第一区二区三区 | 日韩精品一区二区在线观看 | 国产成人午夜高潮毛片 | 日本成人二区 | 国产乱淫a∨片免费观看 | 亚洲欧美日韩免费 | 免费a视频| 日本综合久久 | 男人天堂免费 | 福利一区二区三区视频在线观看 | 久久午夜免费视频 | 久久久国产一级片 | 电影91| a网在线 | 天堂成人国产精品一区 | bt 自拍 另类 综合 欧美 | 久草在线视频网 | 免费啪啪 | 日韩视频一二区 |