Java 通过套接字发送时,定时被删除的问题

Java 通过套接字发送时,定时被删除的问题,java,sockets,object,time,Java,Sockets,Object,Time,我设置了一个游戏,在这个游戏中,我通过服务器和客户端之间的套接字发送一组塔和部队对象,出于某种原因,攻击率和动画(这让我相信计时属性)被忽略/编辑。这是塔楼等级: package jandek.towers; import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOExce

我设置了一个游戏,在这个游戏中,我通过服务器和客户端之间的套接字发送一组塔和部队对象,出于某种原因,攻击率和动画(这让我相信计时属性)被忽略/编辑。这是塔楼等级:

package jandek.towers;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import jandek.handler.Handler;
import jandek.main.Frame;
import jandek.main.Game;
import jandek.utils.Utils;


public abstract class Tower implements Serializable{

private int range;
private double attackDMG;
private double attackSPEED; //1 = 1/60 seconds
private byte[][][] image;
private int x;
private int y;
private long lastAttackTime;
private int multiplier;
private int level; //0 = 1;
private boolean moving;
private boolean rangeNeedsToBeDrawn;
private int width = 32;
private int height = 32;
//private BufferedImage[][][] bufferedImages = new BufferedImage[16][4][2];
private ArrayList<Integer> troopsInTroopsArrayThatAreInRange;
private int animationFrame = 0;
private int animationFrameSpeed = 60; //nano seconds between changes
private double animationFrameLastChange; //last change
boolean attacked;
boolean animation = false;
/**
 * 
 * @param x
 * @param y
 * @param level
 * @param multiplier
 * @param range
 * @param attackDMG
 * @param attackSPEED
 * @param image
 */
public Tower(int x, int y, int level, int multiplier, int range, double attackDMG, double attackSPEED, byte[][][] image){
    troopsInTroopsArrayThatAreInRange = new ArrayList<Integer>();
    this.x = x;
    this.y = y;
    this.range = range;
    this.attackDMG = attackDMG + (level * multiplier);
    this.attackSPEED = attackSPEED;
    this.image = image;
    this.level = level;
    this.multiplier = multiplier;
    lastAttackTime = Handler.getGame().getTime();
    moving = false;
    rangeNeedsToBeDrawn = true;

}
public void update(){
    attacked = false;
    if(moving == true){
        setX(Frame.getMouseX());
        setY(Frame.getMouseY());
    }
    AttackTarget();
    if(attacked){
        animation = true;
        animationFrameLastChange = Handler.getGame().getTime();
        animationFrame = 1;
        //Handler.getGame().getLogWriter().write("Animation is at the second image");
    }

    if(animation && Handler.getGame().getTime() - animationFrameLastChange >= animationFrameSpeed){
        animationFrame = 0;
        animation = false;
        }
}

private void AttackTarget(){
    if((Handler.getGame().getTime() - lastAttackTime) > attackSPEED && !moving){
        for(int i = 0; i < Handler.getTroops().size() ; i++){
            int x1 = this.x + this.width / 2;
            int y1 = this.y + this.height / 2;
            int x2 = Handler.getTroops().get(i).getX() + Handler.getTroops().get(i).getSize() / 2;
            int y2 = Handler.getTroops().get(i).getY() + Handler.getTroops().get(i).getSize() / 2;
            if(Utils.getDistance(x1, y1, x2, y2) <= range){
                troopsInTroopsArrayThatAreInRange.add(i);
                attacked = true;
            }
        }
    }

    if(attacked){
        Handler.getGame().getLogWriter().write("");
        Handler.getGame().getLogWriter().write(Handler.getGame().getTime() - lastAttackTime + " : " + attackSPEED);
        lastAttackTime = Handler.getGame().getTime();
        Handler.getGame().getLogWriter().write(Handler.getGame().getTime() - lastAttackTime + " : " + attackSPEED);
        Handler.getGame().getLogWriter().write("");
        double min = range;
        int nearestTroop = -1;
        for(int j = 0; j < troopsInTroopsArrayThatAreInRange.size(); j++){
            int x1 = this.x + this.width / 2;
            int y1 = this.y + this.height / 2;
            int x2 = Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getX() + Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getSize() / 2;
            int y2 = Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getY() + Handler.getTroops().get(troopsInTroopsArrayThatAreInRange.get(j)).getSize() / 2;
            if(Utils.getDistance(x1, y1, x2, y2) < min){
                min = Utils.getDistance(x1, y1, x2, y2);
            //  Handler.getGame().getLogWriter().write("troop distance checked");   
                nearestTroop = troopsInTroopsArrayThatAreInRange.get(j);
            }
        }
        Handler.getTroops().get(nearestTroop).changeHealth(-(int)attackDMG);
        troopsInTroopsArrayThatAreInRange.clear();
    }


}

}
上面的每个“1”都会在run方法的末尾打印出来,从而表明

Handler.getGame().getTime()-lastAttackTime

不知怎的被插座干扰了。有什么想法吗?我希望我没有遗漏一些过于明显或简单的东西

编辑套接字代码:

private void updateConnection(){
        if(isClientActive()){
            if(player.getType() == 0){
                client.sendObjects(towers);
            }else{
                client.sendObjects(troops);
            }
            ArrayList<Object> obj = (ArrayList<Object>)client.receiveObjects();
            if(obj != null && obj.size() > 0){
                if (obj.get(0) instanceof Troop) {
                    mendTroops(obj);
                }else if(obj.get(0) instanceof Troop){
                    mendTowers(obj);
                }
            }else{
                if(player.getType() == 0){
                    troops.clear();
                }else{
                    towers.clear();
                }
            }
        }else if(isServerActive()){
            if(player.getType() == 0){
                server.sendObjects(towers);
            }else{
                server.sendObjects(troops);
            }
            ArrayList<Object> obj = (ArrayList<Object>)server.receiveObjects();
            if(obj != null && obj.size() > 0){
                if (obj.get(0) instanceof Troop) {
                    mendTroops(obj);
                }else if(obj.get(0) instanceof Tower){
                    mendTowers(obj);
                }
            }else{
                if(player.getType() == 0){
                    troops.clear();
                }else{
                    towers.clear();
                }
            }
        }
    } 
private void updateConnection(){
if(isClient()){
if(player.getType()==0){
客户。发送对象(塔);
}否则{
客户端。发送对象(部队);
}
ArrayList obj=(ArrayList)client.receiveObjects();
如果(obj!=null&&obj.size()>0){
if(对象获取(0)部队实例){
军事部队(obj);
}else if(对象获取(0)部队实例){
门德塔(obj);
}
}否则{
if(player.getType()==0){
部队。清除();
}否则{
塔。清除();
}
}
}else if(isServerActive()){
if(player.getType()==0){
服务器。发送对象(塔);
}否则{
sendObjects(部队);
}
ArrayList obj=(ArrayList)server.receiveObjects();
如果(obj!=null&&obj.size()>0){
if(对象获取(0)部队实例){
军事部队(obj);
}else if(对象获取塔的(0)实例){
门德塔(obj);
}
}否则{
if(player.getType()==0){
部队。清除();
}否则{
塔。清除();
}
}
}
} 

我在你的帖子中没有看到任何套接字代码,但TCP和UDP都不提供任何时间保证。TCP广泛使用缓冲,以便将传出写入合并到较小数量的导线段中。您可以通过禁用Nagle算法来减轻这一点,但您永远无法从任何网络中获得实时性能。

什么套接字?这里没有sockets代码。我不打算费力地通过代码墙来找出如何计算时间,但如果这取决于正在同步的系统时钟,并且您没有使用NTP设置时钟的系统,那么所有的赌注都是无效的。为了获得更好的帮助,请将代码简化为再现问题的最简单示例。你还不知道问题是什么,你只是从一个症状(发病率不是你期望的)跳到了一个原因(时间被丢弃),这可能是不合理的。减少代码的过程可能会揭示真正的问题。我知道它是在towers中的update()方法(更准确地说是attack()方法)中维持的。我使用一个以60 fps的速度运行的run方法,它存储在一个由tower对象静态访问的变量中。客户端和服务器不必同步,因为它们都使用相同的运行方法并同时启动。在我将套接字系统添加到游戏中之前,我的攻击率一直运行良好,因此我知道它与此有一定的相关性;因此,您必须打印出发送的数据(在发送端)和接收的数据(从接收器)-并进行比较-然后找到问题-我已经看到您正在使用一些奇特的方法,如writeUnshared()-对于初学者,听起来您是混合的,您在哪里看到writeUnshared?是的,问题是接收到的塔阵列并没有改变它的上次攻击时间,它是以任何时候初始化的。我不确定它是否是它的全部属性,但它很奇怪。我将尝试在服务器和clientOk之间如何更新阵列,那么,在两台计算机上运行一个程序,在它们之间发送需要使用攻击速度之类的对象,最好的方法是什么呢?另外,静态检查时间是否重要?您必须将速度作为数据的一部分发送,或者发送时间起点和增量,而不是依赖于零或固定的网络延迟,或者计算机之间的时差为零或固定数量。您能澄清一下速度是什么意思吗?你的意思是我应该在塔的对象中保留一个当前的游戏时间参考吗?这应该是一个评论,而不是一个答案。@JimGarrison你肯定是在开玩笑吧?“从不”在什么方面不是答案?
private void updateConnection(){
        if(isClientActive()){
            if(player.getType() == 0){
                client.sendObjects(towers);
            }else{
                client.sendObjects(troops);
            }
            ArrayList<Object> obj = (ArrayList<Object>)client.receiveObjects();
            if(obj != null && obj.size() > 0){
                if (obj.get(0) instanceof Troop) {
                    mendTroops(obj);
                }else if(obj.get(0) instanceof Troop){
                    mendTowers(obj);
                }
            }else{
                if(player.getType() == 0){
                    troops.clear();
                }else{
                    towers.clear();
                }
            }
        }else if(isServerActive()){
            if(player.getType() == 0){
                server.sendObjects(towers);
            }else{
                server.sendObjects(troops);
            }
            ArrayList<Object> obj = (ArrayList<Object>)server.receiveObjects();
            if(obj != null && obj.size() > 0){
                if (obj.get(0) instanceof Troop) {
                    mendTroops(obj);
                }else if(obj.get(0) instanceof Tower){
                    mendTowers(obj);
                }
            }else{
                if(player.getType() == 0){
                    troops.clear();
                }else{
                    towers.clear();
                }
            }
        }
    }