当前位置: 首页 > 知识库问答 >
问题:

由对等方重置连接或无需关闭套接字

锺离自明
2023-03-14

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

我正在开发一款基于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类型的新服务器Nachricht,找到的玩家作为发送方。协议返回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;
            }
        }
    }

此代码搜索每个现有线程(服务器将它们存储在向量中)并检查该线程连接的播放器是否是协议返回的播放器。当找到线程时,两个线程都会被提供给一个新创建的线程,该线程存储它们两个,同时将该新线程存储在两个线程中。新线程甚至使用两个系统验证连接:

    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();
        }
    }

在外面。书面对象;线任何地方都没有关闭任何东西的线条(我甚至从任何地方拿出了每一个close(),以确保没有任何东西可以干扰),而且似乎根本没有任何模式来确定它何时工作和何时不工作(不工作会关闭服务器和程序clientsocket,因此在这种情况下程序无法工作)。我有没有办法保证我的程序正常运行,或者我有没有出错?我非常绝望,因为我甚至不能做主要的测试来找出一个模式,因为用完全相同的设置启动程序两次仍然会导致它大部分时间都工作。

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

共有2个答案

欧阳意蕴
2023-03-14
  • “连接重置”通常意味着您写入了已被对等方关闭的连接:换句话说,是应用程序协议错误

所有这些都只表明了编码错误。发布更多的代码,我会给你看更多的代码。

邵赞
2023-03-14

这实际上是我犯的一个相当有趣的错误:我的服务器将线程存储在他的向量中,即使它们的套接字断开。因此,使用上次重启后就已经连接到服务器的帐户登录(我在测试外观时用来保持服务器运行)会导致

   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())){

循环以确定其他玩家的线程,以找到较旧且已经关闭的线程,而不是其他玩家目前连接的线程。

 类似资料:
  • 我正在使用Python,并在给定端口上侦听UDP数据包,一切似乎都很好地工作-但经过较长时间后,脚本崩溃,出现以下错误: 当重新启动脚本时,相同的崩溃会在较短的时间后再次发生。相反,重新启动服务器似乎可以再次完全解决问题。 关于插座方面的事情,我正在做: 我是否遗漏了一些显而易见的东西,或者只是有一个简单的方法来避免这种情况? 提前感谢您提供的任何信息! 本吉

  • 我的servlet程序是 如何解决这个问题?

  • 我使用HttpClient4.4发送get和post请求。并且我刚刚创建了一个httpclient的simpile包装器以方便使用: 当我使用这个类发送post请求时。奇怪的事情发生了: 第一次,我向服务器发送一个post请求,一分钟后就可以了,我向服务器发送一个同样的请求,也可以了。但几分钟后,我发出了一个同样的请求,有些不对劲: 但是,我仍然向服务器发送一个相同的请求,它又可以了。 每次我按照

  • 问题内容: 我们正在并行开发一个Python Web服务和一个客户端网站。当我们从客户端向服务发出HTTP请求时,一个调用始终在socket.py中引发socket.error,其读取方式为: 当我用wireshark收听时,“好”和“坏”的响应看起来非常相似: 由于OAuth标头的大小,该请求被分为两个数据包。服务以ACK响应 该服务发送响应,每个报头一个数据包(HTTP / 1.0 200 O

  • 我在RabbitMQ上犯了stainger错误。我发送了一些关于MQ和Php产品的信息,但出现了一些问题。我可以在出现异常“errno=104由对等方重置连接”的一分钟后发送消息。见下文: rabbitmq-3.6的版本。1,php-7.0版本。5,php amqp库的版本-“Videlavaro/php amqplib”:“~2.7 来自rabbitmq的日志:

  • 问题内容: 我使用httpclient 4.4发送get和post请求。我刚刚创建了一个简单的httpclient包装器,以方便使用: 当我使用此类发送帖子请求时。发生了一些奇怪的事情: 第一次,我将发布请求发送到服务器,几分钟后没问题,我将相同的请求发送到服务器,也行。但是几分钟后,我发送了相同的请求,出现了错误: 但是之后,我仍然向服务器发送了相同的请求,再次可以。 每当我按照上述步骤尝试时,