jcreatorqijiashe 2008-12-29 12:50
浏览 488
已采纳

用Mina开发Socket服务器总有一些不可预知的奇怪现象?程序结束不了?!

最近在用 Java的Socket框架mina开发一个服务器端程序,服务器写完后,用mina的客户端API写了程序去连接服务器端,也连接成功了,但是发现每次客户端连接完成运行后 过1分钟客户端程序才结束! 经过调试发现代码已经执行了客户端代码的最后一行! 真是奇怪,客户端代码如下:

public class Client
{
private static final String HOSTNAME = "localhost";
private static final int PORT = 20000;
public static void main( String[] args ) throws Throwable
{
    SocketConnector connector = new SocketConnector();       
    // Configure the service.
    SocketConnectorConfig cfg = new SocketConnectorConfig();
             cfg.getFilterChain().addLast(
                "codec",
                new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );

    cfg.getFilterChain().addLast( "logger", new LoggingFilter() );

    IoSession session;
                try {
            ConnectFuture future = connector.connect(new InetSocketAddress(
                    HOSTNAME, PORT), new ClientSessionHandler("Hi hi :("), cfg);

            future.join();
            session = future.getSession();
                    } catch (RuntimeIOException e) {
            System.err.println("Failed to connect.");
            e.printStackTrace();
                       }

    // wait until the summation is done
    session.getCloseFuture().join();
    System.out.println(session,"### all done!  !");
}





"### all done!  !" 明明都已经打印出来了! 但是发现进程中还是有一个 javaw.exe! 而且用进程管理工具无法结束!,过了1分钟后,这个javaw.exe就没有了,发现eclipse的控制台红色结束按钮也变灰色了. 这些居然都是在最后一行代码执行完发生的? 感觉Java真是一个不稳定的东西~~
问题补充
多谢回复,我看2.0是M版本,好像下载上面写着 unstable,所以没有用,你用这个版本感觉稳定吗?  我刚才又试验了一下 quickServer,试验socket连接到达100个居然就Connnectin refused了? 好像根本没有使用 非阻塞队列. mina虽然有我刚才说的问题,但是他却能坚持到 1000个连接没有发生 Connnectin refused的错误,说明他还是利用了线程池重用了很多连接,我现在马上试试 mina2.0! 我用的是1.1.7,connector没有dispose方法,那个例子我也看到了
问题补充
还有你知道他的 httpserver怎么用吗? asyWeb合到mina里面了,我看了例子"httpserver",但是里面居然没有客户端调用示例.客户端怎么传递参数到http服务器也没有说明
问题补充
我试了一下2.0M果然可以. 但是服务器端好像不能自己设置连接池了? 下面的代码在2.0不能用,你们怎么用连接池的? 我的性能是要求一台服务器机器需要有1000个并发连接. 我现在服务器这样写不知道有没有问题:

ExecutorService executor = Executors.newFixedThreadPool(1000);

    IoAcceptor acceptor = new NioSocketAcceptor();


    acceptor.setHandler(  new TimeServerHandler() );

    acceptor.getSessionConfig().setReadBufferSize( 2048 );
    acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );

    acceptor.getFilterChain().addLast("executor",
            new ExecutorFilter(executor));
    acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
    acceptor.getFilterChain().addLast(
            "codec",
            new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) ); 
    acceptor.bind( new InetSocketAddress(PORT) );</pre>




客户端很简单,就是模拟1000个并发连接:

 public static void main( String[] args ) throws Throwable

{

for(int i=0;i<1000;i++){
log.info("Enter run l..."+i);
new Thread(new ClientThread(i)).start();
}
     }    </pre>


每个客户端代码是:

public void run() {
// TODO Auto-generated method stub
log.info("#### thread :"+this.num+" Running...");
NioSocketConnector connector = new NioSocketConnector();
// Configure the service.
    connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);


    connector.getFilterChain().addLast(
                "codec",
                new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );

    connector.getFilterChain().addLast( "logger", new LoggingFilter() );
    connector.setHandler(new ClientSessionHandler(" hihi new!"));


    IoSession session;
    for (;;) {
        try {
            ConnectFuture future = connector.connect(new InetSocketAddress(
                    HOSTNAME, PORT));

            future.awaitUninterruptibly();
            session = future.getSession();
            break;
        } catch (Exception e) {
            System.err.println("Failed to connect.");
            e.printStackTrace();

        }
    }

    // wait until the summation is done
    session.getCloseFuture().awaitUninterruptibly();

    connector.dispose();
    log.info("#### thread :"+this.num+" over ...");

}</pre>


不知道这样写是不是已经用了NIO特性和数量是1000的连接池了. 而且我发现客户端如果不用mina的API,直接用Socket API连接,服务器撑不到1000个,200多个就Connection refused了.
问题补充
刚才试验了一下,模拟1000个客户端连接,成功了931个,异常是:

2008-12-28 02:18:06,968 ERROR (LoggingFilter.java:127) - EXCEPTION :
java.io.IOException: 您的主机中的软件放弃了一个已建立的连接。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:25)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:233)
at sun.nio.ch.IOUtil.read(IOUtil.java:206)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:207)
at org.apache.mina.transport.socket.nio.NioProcessor.read(NioProcessor.java:180)
at org.apache.mina.transport.socket.nio.NioProcessor.read(NioProcessor.java:42)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:568)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:547)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:539)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$400(AbstractPollingIoProcessor.java:57)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:867)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:65)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)


不知道调整哪些参数可以不发生这个错误? 就是说调整什么可以使1000个连接都能连上
问题补充
windows需要修改OS的一个设置,但是设置了也不起作用,我再试试吧! java的NIO的目的是使服务器端打开尽量少的Socket连接,能处理尽可能多的客户端请求(不知道主要是非阻塞队列起作用还是那个concurrent线程池在发挥作用,应该是前者),这样理解没错吧?
  • 写回答

17条回答 默认 最新

  • pigo2004 2008-12-29 12:50
    关注

    mina 1.1.x版本貌似是 session.close();

    对应的方法定义是: CloseFuture close();

    mina 2.0更简单好用。不过我们不是直接用。是参考2.0做了些裁减。

    mina的性能没什么可担心的,成功案例有:openfire

    可以google一下:openfire connection manager

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(16条)

报告相同问题?

悬赏问题

  • ¥15 优质github账号直接兑换rmb,感兴趣伙伴可以私信
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办
  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)