亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java Socket無法完全接收返回內容的解決方案

 更新時間:2021年10月27日 14:19:51   作者:LVXIANGAN  
這篇文章主要介紹了java Socket無法完全接收返回內容的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

最近在使用Socket通訊時,遇到了接收內容不全(返回內容 = 4字節(jié)報文長度 + 內容主體)的問題:客戶端發(fā)送請求數(shù)據(jù),服務器明明返回了73個字節(jié)內容,但客戶端有時能全部接收,但有時卻只能返回4個字節(jié)。

一開始是懷疑服務器返回有問題,但使用調試工具連續(xù)測試了很多次,結果顯示:服務器的確每次都返回了73個字節(jié)內容。那很明顯了,問題出現(xiàn)在客戶端代碼上。

錯誤現(xiàn)象

再來看看調試工具結果:

讓我們來看看客戶端代碼,調用方法如下:(該方法適用于返回報文前兩個字節(jié)表示長度的情況:2字節(jié)報文長度 + 內容主體)

public static void test() {
		SocketClient client = new SocketClient();
		// 建立socket對象
		int iret = client.connect("192.168.1.105", 1234);
		if (iret == 0) {
			// 發(fā)送數(shù)據(jù)
			client.write("helloworld".getBytes());
			// 接收數(shù)據(jù)
			byte data[] = client.read();
			if ((data != null) && (data.length != 0)) {
				// 處理接收結果
				Utils.print("響應報文字節(jié)數(shù)組---->" + Arrays.toString(data));
			}
		}		
	}

SocketClient.java源碼:

public class SocketClient { 
	// 存儲接收數(shù)據(jù)
	private byte m_buffer[] = new byte[0x10000];
	private Socket m_socket;
	private InputStream m_inputstream;
	private OutputStream m_outputstream;
	private BufferedInputStream m_bufferedinputstream;
	private BufferedOutputStream m_bufferedoutputstream;
	private boolean connected; 
	public int connect(String host, int port) {
		try {
			SocketAddress socketAddress = new InetSocketAddress(host, port);
			m_socket = new Socket();
			m_socket.connect(socketAddress, 5000);
			m_socket.setSoTimeout(60000);
 
			m_inputstream = m_socket.getInputStream();
			m_bufferedinputstream = new BufferedInputStream(m_inputstream);
			m_outputstream = m_socket.getOutputStream();
			m_bufferedoutputstream = new BufferedOutputStream(m_outputstream);
		} catch (Exception e) {
			return -1;
		}
		connected = true;
		return 0;
	}
 
	/**
	 * 發(fā)送請求數(shù)據(jù)
	 * 
	 * @param data
	 * @param start
	 * @param end
	 * @return
	 */
	public int write(byte data[]) {
		if (data == null || data.length == 0 || !connected) {
			return 0;
		}
		try {
			m_bufferedoutputstream.write(data, 0, data.length);
			m_bufferedoutputstream.flush();
		} catch (Exception e) {
			return -1;
		}
		return 0;
	}
	
	/**
	 * 讀取返回數(shù)據(jù)
	 * 
	 * @return
	 */
	public byte[] read() {
		if (!connected) {
			return null;
		}
		int len = -1;
		try {
			// 長度不正確,有時返回4,有時返回73
			len = m_bufferedinputstream.read(m_buffer, 0, 0x10000);
		} catch (Exception e) {
			len = 0;
		}
		if (len != -1) {
			return null;
		} else {
			byte ret[] = new byte[len];
			for (int i = 0; i < len; i++) {
				ret[i] = m_buffer[i];
			}
			return ret;
		}
	}
}

通過代碼調試,發(fā)現(xiàn)問題出現(xiàn)在inputsream.read方法上,java API對其描述如下:

int java. io. BufferedInputStream.read( byte[] buffer, int offset, int byteCount) throws IOException

Reads at most byteCount bytes from this stream and stores them in byte array buffer starting at offset offset. Returns the number of bytes actually read or -1 if no bytes were read and the end of the stream was encountered. If all the buffered bytes have been used, a mark has not been set and the requested number of bytes is larger than the receiver's buffer size, this implementation bypasses the buffer and simply places the results directly into buffer.

Overrides: read(...) in FilterInputStream
Parameters:
buffer the byte array in which to store the bytes read.
offset the initial position in buffer to store the bytes read from this stream.
byteCount the maximum number of bytes to store in buffer.
Returns:
the number of bytes actually read or -1 if end of stream.
Throws:
IndexOutOfBoundsException - if offset < 0 or byteCount < 0, or if offset + byteCount is greater than the size of buffer.
IOException - if the stream is already closed or another IOException occurs.

引起錯誤原因在于

客戶端在發(fā)送數(shù)據(jù)后,過快地執(zhí)行read操作,而這時服務端尚未完全返回全部內容,因此只能讀到部分字節(jié)。于是換了個思路:

public class SocketClient { 
	private Socket m_socket;
	private InputStream m_inputstream;
	private OutputStream m_outputstream;
	private BufferedInputStream m_bufferedinputstream;
	private BufferedOutputStream m_bufferedoutputstream;
	private boolean connected; 
	public int connect(String host, int port) {
		try {
			SocketAddress socketAddress = new InetSocketAddress(host, port);
			m_socket = new Socket();
			m_socket.connect(socketAddress, 5000);
			m_socket.setSoTimeout(60000);
 
			m_inputstream = m_socket.getInputStream();
			m_bufferedinputstream = new BufferedInputStream(m_inputstream);
			m_outputstream = m_socket.getOutputStream();
			m_bufferedoutputstream = new BufferedOutputStream(m_outputstream);
		} catch (Exception e) {
			return -1;
		}
		connected = true;
		return 0;
	}
 
	/**
	 * 發(fā)送請求數(shù)據(jù)
	 * 
	 * @param data
	 * @param start
	 * @param end
	 * @return
	 */
	public int write(byte data[]) {
		if (data == null || data.length == 0 || !connected) {
			return 0;
		}
		try {
			m_bufferedoutputstream.write(data, 0, data.length);
			m_bufferedoutputstream.flush();
		} catch (Exception e) {
			return -1;
		}
		return 0;
	}
	
	/**
	 * 讀取返回數(shù)據(jù)
	 * 
	 * @return
	 */
	public byte[] read() {
		if (!connected) {
			return null;
		}
		try {
			return readStream(m_bufferedinputstream);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * @功能 讀取流
	 * @param inStream
	 * @return 字節(jié)數(shù)組
	 * @throws Exception
	 */
	public static byte[] readStream(InputStream inStream) throws Exception {
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = inStream.read(buffer)) != -1) {
			outSteam.write(buffer, 0, len);
		}
		outSteam.close();
		inStream.close();
		return outSteam.toByteArray();
	}
	
	public static void test() {
		SocketClient client = new SocketClient();
		// 建立socket對象
		int iret = client.connect("192.168.1.105", 1234);
		if (iret == 0) {
			// 發(fā)送數(shù)據(jù)
			client.write("helloworld".getBytes());
			// 接收數(shù)據(jù)
			byte data[] = client.read();
			if ((data != null) && (data.length != 0)) {
				// 處理接收結果
				Utils.print("響應報文字節(jié)數(shù)組---->" + Arrays.toString(data));
			}
		}		
	}
}

測試通過.....

可參考以下解決思路

protected byte[] readMessage(BufferedInputStream is) throws IOException {
		//        MyLog.d(TAG,"=======>readMessage--inputStream=" );
		        int offset = 0;
		        int messageStartOffset = -1;
		        int wait = 0;
		        int messageEndOffset = -1;
		        int findStartOffset = -1;
 
		        while(messageEndOffset==-1||(messageEndOffset+2)>offset){
		            if(is.available()==0){
		                try {
		                    Thread.sleep(MESSAGE_WAIT_INTERVAL);
		                    wait += MESSAGE_WAIT_INTERVAL;
		                } catch (InterruptedException ex) {
		                }
		                if(wait>=MESSAGE_OVERTIME){
		                //超時錯誤
		                    throw new RuntimeException(EXCEPTION_TIMEOUT);
		                }
		                continue;
		            }
		            
		            offset += is.read(messageBuffer, offset, is.available());//讀出數(shù)據(jù)
		            TestMessage.showBytes(messageBuffer, 0, offset, "MESSAGE");
		            if(messageStartOffset==-1){ //未找到報文頭
		                if(findStartOffset<0)
		                    findStartOffset = 0;
		                messageStartOffset = findStartOffset(messageBuffer, findStartOffset, offset);//查找報文頭
		                MyLog.e(TAG, "messageStartOffset="+messageStartOffset);
		                if(messageStartOffset>=0){//找到報文頭
		                    if(messageStartOffset<2){
		                        //報文錯誤
		                        throw new RuntimeException(EXCEPTION_MSG_PARSE_ERROR);
		                    }else{
		                        int iMessageLength = ((messageBuffer[messageStartOffset-2]&0xff)<<8)+
		                         (messageBuffer[messageStartOffset-1]&0xff);
		//                        MyLog.e(TAG, "iMessageLength="+iMessageLength);
		                        int ignoreInvalidLength = messageStartOffset-4;
		                        messageEndOffset = iMessageLength + ignoreInvalidLength;
		//                        MyLog.e(TAG, "messageStartOffset="+messageStartOffset);
		                        MyLog.e(TAG, "messageEndOffset="+messageEndOffset);

如果想要讓程序保證讀取到count個字節(jié),最好用以下代碼:

int count = 100;  
byte[] b = new byte[count];  
int readCount = 0; // 已經成功讀取的字節(jié)的個數(shù)  
while (readCount < count) {  
    readCount += inStream.read(b, readCount, count - readCount);  
}  

這樣就能保證讀取100個字節(jié),除非中途遇到IO異?;蛘叩搅藬?shù)據(jù)流的結尾情況!

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

相關文章

  • java實現(xiàn)簡單圖書管理系統(tǒng)

    java實現(xiàn)簡單圖書管理系統(tǒng)

    這篇文章主要為大家詳細介紹了java實現(xiàn)簡單圖書管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Java定時清理過期文件的實例代碼

    Java定時清理過期文件的實例代碼

    這篇文章主要介紹了Java定時清理過期文件的實例代碼,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2018-12-12
  • spring Retryable注解實現(xiàn)重試詳解

    spring Retryable注解實現(xiàn)重試詳解

    這篇文章主要介紹了spring Retryable注解實現(xiàn)重試詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Spring Data中domain模塊的使用

    Spring Data中domain模塊的使用

    Spring Data是一個流行的數(shù)據(jù)訪問框架,本文主要介紹了Spring Data中domain模塊的使用,并展示如何使用它來優(yōu)化我們的數(shù)據(jù)訪問層,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • springMVC的生命周期詳解

    springMVC的生命周期詳解

    本篇文章主要介紹了springMVC的生命周期詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • java編程多線程并發(fā)處理實例解析

    java編程多線程并發(fā)處理實例解析

    這篇文章主要介紹了java編程多線程并發(fā)處理實例解析,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Java根據(jù)URL下載文件到本地的2種方式(大型文件與小型文件)

    Java根據(jù)URL下載文件到本地的2種方式(大型文件與小型文件)

    這篇文章主要給大家介紹了關于Java根據(jù)URL下載文件到本地的2種方式,分別是大型文件與小型文件,避免內存溢出OOM,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • java實現(xiàn)圖片無損任意角度旋轉

    java實現(xiàn)圖片無損任意角度旋轉

    這篇文章主要為大家詳細介紹了java實現(xiàn)圖片無損任意角度旋轉,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • 淺析Java中的 new 關鍵字

    淺析Java中的 new 關鍵字

    java中的new關鍵字是實例化對象,接下來本文通過一個案例給大家講解Java中的 new 關鍵字,感興趣的朋友可以參考下
    2016-08-08
  • Java OpenCV利用KNN算法實現(xiàn)圖像背景移除

    Java OpenCV利用KNN算法實現(xiàn)圖像背景移除

    這篇文章主要為大家介紹了Java OpenCV利用K最鄰近(KNN,K-NearestNeighbor)分類算法實現(xiàn)圖像背景移除的示例代碼,需要的可以參考一下
    2022-01-01

最新評論