[java] ピアまたはソケットによる接続のリセットが何もせずに終了しました


Answers

  • 'connection reset'は通常、ピアによってすでに閉じられていた接続に書き込んだことを意味します。つまり、アプリケーションプロトコルエラーです。
  • 'socket closed'とは、ソケット閉じてから引き続き使用すること意味します
  • これらはどちらも「どこからも」出てこない。 どちらもアプリケーションのバグを示しています。
  • isConnected()は適切なテストではありません。 ピアが切断すると、魔法のように偽になることはありません。 切断してもそれが間違っているかどうかはわかりません。

これは、バグをコードする以外の何ものでもありません。 あなたのコードをもっと投稿して、もう少しあなたのコードを表示します。

Question

これまで私は問題が発生したときにこのサイトを使いましたが、解決策も見つけましたが、今回は何が起こっているのか分かりません。

私は、1対1マルチプレイヤーモードに基づいたゲームに取り組んでいます。 これまで私はクライアントとサーバーと私のプログラムを作成しました。

私のサーバーは、サーバーに接続するすべてのクライアント用のソケットを持つ新しいスレッドを作成し、ゲーム内で「新しいゲーム」ボタンが押されると、スレッドは今すぐ新しいゲームを探している別のスレッドを探しますゲームを開始したことを知らせるメッセージを両方のスレッドに送信する別々のスレッドを作成し、それがソケットを介して対応するプログラムに送信されます。

ここに私のコードです:

糸:

    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)、送信者(player)、およびメッセージ(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;
            }
        }
    }

このコードは、既存のすべてのスレッド(サーバーがそれらをベクトルに格納します)を検索し、接続されたスレッドがそのプロトコルによって返されたプレイヤーであるかどうかを確認します。 スレッドが検出されると、両方のスレッドは、両方のスレッドに新しいスレッドを格納しながら、両方を格納する新しく作成されたスレッドに渡されます。 新しいスレッドは、2つのsysoutsとの接続を検証します。

    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%の時間で完璧に動作することです(両方のプログラムが "ゲーム開始"モードに入ります)が、時にはプログラムだけで動作します。ソケットのクローズドエラー

    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);にあります。 ライン。 何も閉じない線はありません(何も干渉しないようにどこからでもすべてのclose()を取り出しています)、動作しているときとそうでないときのパターンが全くないようです(サーバーとプログラムのclientsocketが正常に動作しないため、プログラムが正常に動作しない場合があります)。 私のプログラムが確実に動作することを保証する方法はありますか? 私はむしろ必死です。なぜなら、まったく同じ設定でプログラムを2回起動してもパターンを見つけるための大きなテストをすることさえできないからです。

編集:文字通り、ちょうど1人のプレイヤーが新しいゲームモードに入っている間に、もう1人はメインメニューに残りました(その結果、Connectionはサーバーのピア:ソケット書き込みエラーをリセットしました) 3回目は同じ走行で何の問題もない。 だから私は両方のプレイヤーで検索したが、1人だけがゲーム画面に入った(そしてもう1人はエラーが出た)。 私はメインメニューに戻って同じ結果を出して同じことをやりました。 私が3回目に挑戦したとき、それは働き、両方のプレイヤーがゲーム画面に入り、互いにやりとりを始めました。




Links