首页 > 解决方案 > Java:TCP Socket 数据丢失

问题描述

我正在尝试为我的游戏创建一个服务器(当然还有一个客户端)。它是用 Java 开发的,没有额外的库或外部工作。当前设置了客户端和服务器连接,它将定义的字节数(512)作为“包”发送。每个包都有一个用于其类型的 ID(1 个字节)和一个用于其数据的主体(511 个字节)。一般来说,这种联系似乎有效。我目前面临的问题是,当我尽可能快地发送大量数据(地图 ~ 10kb ~ 1300 包)时,我似乎丢失了消息或接收到错误的消息(例如:错误的包 ID )。我似乎无法弄清楚为什么会这样。据我了解,Java 中的套接字使用 TCP 协议,据我所知,这应该可以防止这些问题。

这是服务器的重要(在我看来)部分:

void sendToClient(Queue<DataPackage> packages) {
    if(isConnected()){
        try {
            while(!packages.isEmpty()){
                this.out.write(packages.get().getByteData());
                packages.remove();
                this.out.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
            if(!isConnected()){
                if(!ended){
                    ended = true;
                    server.getServerManager().getEventManager().publishServerEvent(new ServerLostConnectionToClientEvent(id, connection));
                }
            }
        }
    }
}

这是客户的重要(在我看来)部分:

private void acceptData() throws UnsupportedPackageException {
    byte[] income = new byte[DataPackage.MAXPACKAGELENGTH];
    try {
        for(int length = in.read(income); length!=-1 && isConnected(); length = in.read(income)){
            income = Arrays.copyOf(income, DataPackage.MAXPACKAGELENGTH);   

            DataPackage dataPackage = null;
            try {
                dataPackage = new DataPackage(income, length);
            } catch (Exception ea) {ea.printStackTrace();}

            if(dataPackage!=null){

                if(!this.dataStreams.containsKey(dataPackage.getId())) this.dataStreams.put(dataPackage.getId(), new Queue<DataPackage>());
                Queue<DataPackage> dataStream = dataStreams.get(dataPackage.getId());
                if(dataPackage.isEnd()) {
                    this.dataStreams.remove(dataPackage.getId());   
                    handNewDataPackage(dataPackage, dataStream);
                }                   
            }

            income = new byte[DataPackage.MAXPACKAGELENGTH];
        }
    } catch (IOException e) {
        e.printStackTrace();
        if(this.client.run() && !ended){
            this.client.endClient();
            this.client.connectionLost(new ClientLostConnectionToServerEvent(this.socket));
        }
        ended = true;
    }
}

这就是我设置连接的方式:

socket = new Socket(ip, port);
        socket.setTcpNoDelay(false);
        socket.setReceiveBufferSize(DataPackage.MAXPACKAGELENGTH);
        socket.setSendBufferSize(DataPackage.MAXPACKAGELENGTH);

        this.out = new BufferedOutputStream(socket.getOutputStream(), DataPackage.MAXPACKAGELENGTH);
        this.in = new BufferedInputStream(socket.getInputStream(), DataPackage.MAXPACKAGELENGTH);

您可以在此处查看整个项目(如果需要):https ://github.com/reschiram/Game (最新分支:G-9)

如果这看起来只是关于如何编写 Java 套接字的另一个重复问题,我很抱歉。我也在这里看到了几个类似的问题,但似乎没有一个完全适合我的问题(或帮助我解决它)。

标签: javasocketstcp

解决方案


推荐阅读