国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久久久久亚洲av毛片大全 | 亚洲成人精品久久久 | 成人h漫在线观看 | 男女全黄一级一级高潮免费看 | 亚洲精品国产电影 | 免费观看aaa | 美女扒开尿口来摸 | 高清一区二区 | 黄色片在线免费观看 | 中文字幕高清视频 | 亚洲日韩欧美一区二区在线 | 九九综合九九 | 中文字幕在线综合 | 欧美国产精品一区二区三区 | 免费看国产片在线观看 | 亚洲精品综合中文字幕 | 日韩精品免费一区二区夜夜嗨 | 亚洲精品9999 | 亚洲免费看av | 人人做人人澡人人爽欧美 | 午夜精品久久久久 | 亚洲人免费视频 | 国内精品视频在线观看 | 99伊人| 色婷婷久久一区二区三区麻豆 | 日韩美女乱淫aaa高清视频 | 91视频导航 | 免费黄色在线 | 婷婷成人av | 亚洲精品久久久久中文字幕欢迎你 | 爱爱免费看 | 亚洲成av人影片在线观看 | 精品福利视频网站 | 亚洲精品一区二区在线观看 | 欧美日视频 | 国产在线乱 | 99re6在线视频精品免费 | 美女久久久 | 亚洲一区 中文字幕 | 一区视频在线播放 | 久在线 |