通过对等或套接字重置连接无关紧要

时间:2015-09-25 09:12:02

标签: java sockets server

到目前为止,每当我遇到问题时我都会使用此网站,而且我也找到了解决方案,但这次我不知道发生了什么。

我正在开发一款基于1-vs-1-multiplayer模式的游戏。到目前为止,我已经与客户创建了一个服务器和我的程序。

我的服务器为每个与服务器连接的客户端创建一个带有套接字的新线程,当在游戏中按下" New Game" -Button时,线程会搜索另一个正在寻找的线程现在一个新游戏,一旦找到他,就创建一个单独的线程,向两个线程发送一条消息,通知他们游戏已经开始,然后通过他们的套接字发送给相应的反应程序。

这是我的代码:

主题:

    public void run() {

    try {

        out = new ObjectOutputStream(socket.getOutputStream());
        in = new ObjectInputStream(socket.getInputStream());
        ServerNachricht inputLine, outputLine;
        LabyrinthProtocol prot = new LabyrinthProtocol();


        while (socket.isConnected()) {

ServerNachricht是一个由类型(int),发送者(播放器)和消息(String)组成的类。 当线程获得新游戏消息时,协议将玩家状态值更改为"搜索"然后查看另一个"搜索"玩家存在,然后将玩家的价值观改为"玩"并返回一个类型为Kampfbeginn的新ServerNachricht,找到的播放器为发件人。 在协议返回outputLine之后,这就是线程的作用:

                    if (outputLine.getArt() == ServerNachricht.KAMPFBEGINN) {
                    System.out.println(outputLine.getSender().getSname()+" ist da");    
                    server.kampfbeginn(this, outputLine.getSender());
                }

sysout只是验证协议实际上是否找到了另一个玩家,并且正在打印该玩家的名字以确定。到目前为止,这一直都有效。 以下是在服务器中调用新游戏的部分:

    public void kampfbeginn(LabyrinthThread t, Spieler gegner) {
    KampfThread kampf = null;
    System.out.println(gegner.getSname()+" anerkannt");
    for(int i = 0;i<threads.size();i++){
        if(threads.get(i)!=null){
            System.out.println(threads.get(i).getSpieler().getSname());
            if(threads.get(i).getSpieler().getSname().equals(gegner.getSname())){
                LabyrinthThread gegnert = threads.get(i);
                kampf = new KampfThread(t,gegnert);
                t.setKampf(kampf);
                gegnert.setKampf(kampf);
                break;
            }
        }
    }

此代码搜索每个现有线程(服务器将它们存储在向量中)并检查连接的线程是否是协议返回的播放器。找到线程后,两个线程都被赋予一个新创建的线程,该线程存储它们,同时还在两个线程中存储该新线程。 新线程甚至验证与两个sysout的连接:

    public KampfThread(LabyrinthThread spieler1, LabyrinthThread spieler2) {
    super();
    this.spieler1 = spieler1;
    this.spieler2 = spieler2;
    System.out.println(spieler1.getSpieler().getSname() + "ist drin");
    System.out.println(spieler2.getSpieler().getSname() + "ist drin");

}

我每次都会得到。 建立两个连接后,该线程向两个线程发送一条消息,以便它们通知程序启动:

        case(ServerNachricht.KAMPFBEGINN):
        spieler1.ThreadNachricht(new ServerNachricht(ServerNachricht.KAMPFBEGINN,spieler2.getSpieler(),""));
        spieler2.ThreadNachricht(new ServerNachricht(ServerNachricht.KAMPFBEGINN,spieler1.getSpieler(),""));
        break;

在线程中调用此方法:

    public void ThreadNachricht(ServerNachricht s) {

    if(socket.isConnected()) {
        try {
            out.writeObject(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

奇怪的是,这种方式在80%的时间内都非常完美(所以这两个程序都进入了#34;游戏开始&#34;模式)但有时它只适用于一个甚至两个程序和服务器得到一个 连接由同行重置 或者a 套接字关闭

中的错误
    public void ThreadNachricht(ServerNachricht s) {

    if(socket.isConnected()) {
        try {
            out.writeObject(s);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
out.writeObject(s)中的

;线。在任何地方都没有任何关闭任何东西的行(我甚至从任何地方取出每一个关闭()以确保没有任何东西可以干扰)并且似乎根本没有任何模式,当它工作时和它没有#39; t(并且不工作关闭服务器和程序clientocket,因此当发生这种情况时程序无法工作)。有什么方法可以保证我的程序有效或者我做了什么错误?我非常绝望,因为我甚至不能进行重大测试来找出一个模式,因为启动程序两次完全相同的设置仍然会使它在大多数时间工作。

编辑:我确实有一种情况,其中一个玩家进入新的游戏模式,而另一个玩家停留在主菜单中(导致服务器连接重置:服务器的套接字写入错误)连续两次在第三次工作之前,在同一次运行中没有任何问题。所以我搜索了两个玩家,但只有一个进入游戏画面(另一个得到了错误)。然后我按回去进入主菜单并再次使用相同的结果做同样的事情。当我第三次尝试时,它起作用,两个玩家都进入了游戏界面并开始互相交流。

2 个答案:

答案 0 :(得分:1)

这实际上是一个相当有趣的错误:我的服务器将线程存储在他的矢量中,即使他们的套接字断开连接。因此,自从上次重启之前已经连接到服务器的帐户登录(我用来保持服务器在我刚刚测试化妆品时运行)会导致其

   for(int i = 0;i<threads.size();i++){
    if(threads.get(i)!=null){
        System.out.println(threads.get(i).getSpieler().getSname());
        if(threads.get(i).getSpieler().getSname().equals(gegner.getSname())){

循环确定其他玩家找到旧的已经关闭的线程的线程,而不是另一个玩家此时连接的线程。

答案 1 :(得分:0)

  • &#39;连接重置&#39;通常意味着您写入了已被对等方关闭的连接:换句话说,应用程序协议错误。
  • &#39;插座关闭&#39;意味着关闭了套接字,然后继续使用它。
  • 其中任何一个都无处可寻。&#39;两者都表明应用程序错误。
  • isConnected()不是一个合适的测试。当对等设备断开连接时,它并没有神奇地变为错误。即使断开连接,我也不确定它是否会失效。

所有这些只表示编码错误。发布更多代码,我会向您展示更多代码。