国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

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

香港云服务器
服務器之家 - 編程語言 - Java教程 - java Socket無法完全接收返回內容的解決方案

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

2022-03-03 00:32LVXIANGAN Java教程

這篇文章主要介紹了java Socket無法完全接收返回內容的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

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

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

錯誤現象

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

再來看看調試工具結果:

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void test() {
        SocketClient client = new SocketClient();
        // 建立socket對象
        int iret = client.connect("192.168.1.105", 1234);
        if (iret == 0) {
            // 發送數據
            client.write("helloworld".getBytes());
            // 接收數據
            byte data[] = client.read();
            if ((data != null) && (data.length != 0)) {
                // 處理接收結果
                Utils.print("響應報文字節數組---->" + Arrays.toString(data));
            }
        }      
    }

SocketClient.java源碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class SocketClient {
    // 存儲接收數據
    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;
    }
 
    /**
     * 發送請求數據
     *
     * @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;
    }
    
    /**
     * 讀取返回數據
     *
     * @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;
        }
    }
}

通過代碼調試,發現問題出現在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.

引起錯誤原因在于

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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;
    }
 
    /**
     * 發送請求數據
     *
     * @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;
    }
    
    /**
     * 讀取返回數據
     *
     * @return
     */
    public byte[] read() {
        if (!connected) {
            return null;
        }
        try {
            return readStream(m_bufferedinputstream);
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * @功能 讀取流
     * @param inStream
     * @return 字節數組
     * @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) {
            // 發送數據
            client.write("helloworld".getBytes());
            // 接收數據
            byte data[] = client.read();
            if ((data != null) && (data.length != 0)) {
                // 處理接收結果
                Utils.print("響應報文字節數組---->" + Arrays.toString(data));
            }
        }      
    }
}

測試通過.....

可參考以下解決思路

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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());//讀出數據
                    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個字節,最好用以下代碼:

?
1
2
3
4
5
6
int count = 100
byte[] b = new byte[count]; 
int readCount = 0; // 已經成功讀取的字節的個數 
while (readCount < count) { 
    readCount += inStream.read(b, readCount, count - readCount); 
}

這樣就能保證讀取100個字節,除非中途遇到IO異常或者到了數據流的結尾情況!

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

原文鏈接:https://blog.csdn.net/LVXIANGAN/article/details/72817478

延伸 · 閱讀

精彩推薦
896
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 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 午夜精品影院 | 日本综合色 | 在线播放一区 | 国产大学生一区 | 特黄特色大片免费视频观看 | 亚洲不卡视频 | 热久久影院 | 国产目拍亚洲精品99久久精品 | 欧美日本国产 | 夜夜av | 亚洲成人免费影院 | 欧美在线免费 | 91av在线电影 | 亚洲欧美在线播放 | 中文字幕第二十六页页 | 日日麻批免费视频40分钟 | 黄色影院| 亚洲视频欧美视频 | 国产精品久久久久久一区二区三区 | 亚洲视频二区 | 男人的天堂午夜 | 黄色小网站免费观看 | 国产日韩欧美高清 | av在线第一页 | 龙珠z普通话国语版在线观看 | 亚洲一区综合 | 成人aaaa免费全部观看 | 另类在线 | 精品久久久久久久久久久 | 成人在线| 一区二区在线看 | 黄色在线免费 | 久久精品福利 | 97久久精品午夜一区二区 | 国产毛片在线 | 日韩精品一区二区三区四区五区 | 激情网激情五月 | 午夜电影网址 | 日韩一区二区三区在线看 | 日韩一区在线播放 | 精品久久久久久国产 |