Gradle: MessageIOException: 在防火墙上无法向127.0.0.1写入消息[EndOfStream]?

18

我编写了一个简单的测试项目,该项目打开端口9123一段时间,然后退出:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Date;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class TimeServer
{
    private static final int PORT = 9123;
    public static void main( String[] args ) throws IOException
    {
        IoAcceptor acceptor = new NioSocketAcceptor();
        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
        acceptor.setHandler( new TimeServerHandler() );
        acceptor.getSessionConfig().setReadBufferSize( 2048 );
        acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
        acceptor.bind( new InetSocketAddress(PORT) );
    }

    private static class TimeServerHandler extends IoHandlerAdapter {
        @Override
        public void exceptionCaught(IoSession session, Throwable cause ) throws Exception
        {
            cause.printStackTrace();
        }
        @Override
        public void messageReceived( IoSession session, Object message ) throws Exception
        {
            String str = message.toString();
            if( str.trim().equalsIgnoreCase("quit") ) {
                session.close();
                return;
            }
            Date date = new Date();
            session.write( date.toString() );
            System.out.println("Message written...");
        }
        @Override
        public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
        {
            System.out.println( "IDLE " + session.getIdleCount( status ));
        }
    }
}

...

import java.io.IOException;

public class TimeServerTest {


   @Test
   public void runningTimeServerForTime() throws IOException, InterruptedException {

      int period = 15000;

      System.out.println("Running time server for " + period + "ms");

      TimeServer.main(new String[] {});

      Thread.sleep(period);

      System.out.println("Done, exiting");

      System.exit(0);

   }
}

这个测试在 IntelliJ 下并且 Windows 防火墙关闭时运行正常。

当 Windows 防火墙开启时,会出现异常。

>gradle test
:compileJava
Note: PATH\TimeServer.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
:processResources UP-TO-DATE
:classes
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
Unexpected exception thrown.
org.gradle.messaging.remote.internal.MessageIOException: Could not write message [EndOfStream] to '/127.0.0.1:58895'.
        at org.gradle.messaging.remote.internal.inet.SocketConnection.dispatch(SocketConnection.java:111)
        at org.gradle.messaging.remote.internal.hub.MessageHub$ConnectionDispatch.run(MessageHub.java:284)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: An existing connection was forcibly closed by the remote host
        at sun.nio.ch.SocketDispatcher.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
        at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
        at sun.nio.ch.IOUtil.write(IOUtil.java:51)
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
        at org.gradle.messaging.remote.internal.inet.SocketConnection$SocketOutputStream.flush(SocketConnection.java:236)
        at org.gradle.messaging.remote.internal.inet.SocketConnection.dispatch(SocketConnection.java:109)
        ... 6 more

BUILD SUCCESSFUL

发生了什么?

为什么被引用的端口58895与打开的端口9123非常不同?

如何在不禁用防火墙的情况下运行此测试?

为使此测试正常运行,应将哪个程序添加到Windows防火墙的白名单中?


从堆栈跟踪中没有看到您的测试的链接。如果您不启动TimeServer,它也会失败吗? - SubOptimal
Windows 10 手机热点已启用? - Jose Antonio Dominguez Garcia
2个回答

16

这可能与Gradle处理System.exit()调用的方式有关,参见GRADLE-2759

通常情况下,在测试中使用System.exit()调用并不是一个好主意,因为它可能会干扰测试框架(如果一切都从同一个JVM启动,你会突然关闭它)。你应该添加一种优雅地关闭服务器的方法。

需要注意的是,网络错误似乎与您的网络代码或服务器无关: 从堆栈跟踪中的包名称(org.gradle.messaging.remote.internal)可以看出,它来自Gradle。这就是为什么端口不同且与您指定的端口无关的原因。

但不清楚为什么关闭Windows防火墙后可以通过此测试。


7
在我的Spring Boot应用程序中,我没有明确地编写System exit。但是,我在不同的端口上仍然遇到了相同的错误。 - Satish Patro

0

对我来说,这是因为我尝试连接的指定IP地址和端口中有一个打字错误。一旦我纠正了这个错误,客户端就连接到了服务器,而错误(带有未知端口54345或61927)也消失了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接