socket編程

關於socket流關閉與否

1. 發送某段數據的時候 socket是以流的形式發送的 可能會把這段數據分成幾股流 這裏就涉及到分包和黏包問題了
2. 關於socket.read(buffer[])(java語言中) 、socket.recv(bytes[])(python語言中) socket.recv(read_buffer) (c 語言中)的阻塞問題

2.1 此函數之所以稱爲阻塞 是因爲 從客戶端發送到服務器端接收有一定的時間延遲 在java中可以設置這個延遲時間即在客戶端設置socket.readTimeout(6*1000)

2.2 這個函數在各個語言中的解釋除了都是阻塞的還說明了流結束的標記 注意是流結束的標記,而不是某段數據下面我舉例子來詳細解釋這句話

  • 這個方法的解釋都說在流結束的時候java返回-1 c語言和 python返回數據的長度是0 也就是你用socket發送數據後一定要調用socket.close() server端纔會能檢測到-1 或者0(根據不同的語言java是-1 c和python是0)

  • 所以由於socket流的特性 我們研發人員要確定某段數據的結尾 根據結尾來進行後續邏輯數據的處理,如果天真的以-1 和 0來確定結束的標記那就打錯特錯了 因爲只有socket.close掉纔會觸發

  • 我們工作場景中是client端既要發送數據 又要接收服務端的數據 並且要多次進行這樣的操作(交互) 如果單次的話 java 可以勝任因爲 java提供了關閉輸出流還是輸入流的函數

  • 爲了滿足多次交互所以我們不能關閉socket 也就是不調用socket.close。有人說每交互一次就創建一個socket**理論上是可以的但實際上那樣是不可取的因爲太耗費資源** 我們不關閉socket後那樣我們如何確定某段數據是否結尾了呢。我們可以根據發送數據中的特殊字符來確定某段數據結尾了 總之萬不可用0或者-1來確定結尾

下面是我寫的 java代碼

    try {
        while (true) {
            byte[] aa = new byte[5];
            int read = in.read(aa);
            if (read > 0) {
                System.err.println("本次長度:" + read + "::::::");
                for (byte b : aa) {
                    System.err.print(Integer.toHexString(b) + ", ");
                    if (b == 0x7e) break;//根據發送數據中的某幾個特殊字符來判斷髮送數據的結束標記 不然會一直阻塞在while true中
                }
            } else if (read == -1) {// out.close 客戶端調用這句話後才觸發
                System.err.println("流結束了。。。。");
                break;
            } else {
                // 永遠不會執行
                System.err.println("流中的某段結束了。。。。");
            }
        }

    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("無法讀取端口.....");
        //System.exit(0);
    }

下面是我寫的 python代碼

class Server:
    BufferSize = 1024  # 緩衝數組大小
    __mReceiveDatas = []  # 接收數據的list
    __mSendDatas = []

    def __init__(self, ip, port):
        self.socket = socket.socket()
        self.socket.bind((ip, port))
        self.socket.listen(5)
        self.clientSocket, self.addr = self.socket.accept()
        self.client = package_release.Client.Client()

    def receiveMsgFromClient(self):
        while True:
            data = self.clientSocket.recv(Server.BufferSize)
            if len(data) > 0:
                for a in data:
                    self.__mReceiveDatas.append(a)
                if self.__mReceiveDatas[0] == 0x7e and self.__mReceiveDatas[-1] == 0x7e:
                    self.sendMsgToServer()
                    self.sendMsgToClient()
                    break
            else:
                print("socket 流關閉了")
                break

    def sendMsgToServer(self):
        print("\n" + "server端接收上位機傳過來的數據")
        b = ""
        for i in self.__mReceiveDatas:
            print(hex(i), end=", ")
            b += chr(i)
        # 用client 發送數據
        self.client.sendMsgToServer(b.encode("utf-8"))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章