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"))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章