sdlqzql
sdlqzql
采纳率0%
2016-08-31 05:00 阅读 3.9k

java定时器超时后关闭socket出现socket closed 异常的问题

package my.start;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

//创建AutoStart类,让他实现ServletContextListener(服务程序上下文监听器)接口
//实现ServletContextListener接口需要重写contextDestroyed()和contextInitialized()两个方法
//记得要在web.xml文件中加入
//

// my.test.AutoStart

//
//这样,tomcat在启动时,就会同时调用该接口的contextInitialized()方法
//在contextInitialized()方法中,开启一个线程,用soket监听一个端口,从而实现TCP通信
public class AutoStart extends HttpServlet{

private static final long serialVersionUID = 1L;
private int soketPort = 9014;//要监听的服务器端口,可以根据需要进行修改
@Override
public void init() throws ServletException {
    // TODO Auto-generated method stub
    super.init();
    new MyThread().start();//创建一个MyThread线程对象,并启动线程
    System.out.println("开启监听线程");
}


//创建MyThread类,继承Thread方法

class MyThread extends Thread
{
//重写Thread类的run()方法,用来实现MyThread线程的功能
public void run()
{
//System.out.println("测试开始");
try {
ServerSocket ss = new ServerSocket(soketPort);
System.out.println("监听到"+(soketPort+"")+"端口");
while(true){
//System.out.println("已经创建soket");
//ss对象的accept()方法可以监听指定端口有没有TCP连接
//在没有TCP连接之前程序将阻塞在这里
Socket socket = ss.accept();
System.out.println("有客户端接入");
//监听到指定端口有TCP连接后,创建soket对象,程序不再堵塞,往下执行
//创建一个线程,去监听客户端通过TCP发来的数据
Thread sockThread=new SocketTherad(socket);
//启动线程
sockThread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
int timeNum;
class SocketTherad extends Thread{ //继承Thread类来创建线程
Socket socket;
InputStream is;
OutputStream os;
boolean run_flag=true;//控制run()函数是否继续运行标志位

    Timer heartBeatTimer = new Timer(); //心跳包定时器
    private void startHeartBeatThread() {
        TimerTask heartBeatTask = new TimerTask() {
            public void run() {                 
                timeNum++;   
                System.out.println("timerNum="+(timeNum+""));   
                if(timeNum==2){//超时则关闭socket连接及定时器
                    try {
                        is.close();
                        os.close();//关闭输出流
                        socket.close();//关闭soket
                        run_flag=false;//跳出死循环
                        System.out.println("TCP连接断开");  
                        heartBeatTimer.cancel();//关闭定时器
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        };
        heartBeatTimer.schedule(heartBeatTask, 10*1000, 10*1000);
    }

    public  SocketTherad(Socket socket) {
        this.socket = socket;//传递过来的soket参数赋予给socket对象
    }

    public void run() {//run()函数用来实现线程要完成的任务
        startHeartBeatThread();
        while(run_flag)
        {
            try {
                String str = null;
                is = socket.getInputStream();//获取输入流
                os=socket.getOutputStream();
                byte[] buffer = new byte[200];//数据缓冲区;
                int length=0;
                length = is.read(buffer);//读取接收到的数据流长度

                if(length != (-1)){//不是-1,说明读取到有效的数据
                    str = new String(buffer,0,length);//输入流转换成str字符串                      
                    System.out.print("收到数据:");
                    System.out.println(str);
                }
                else if(length == (-1)){//接收到数据长度为-1,说明客户端主动关闭了TCP连接
                    is.close();//关闭输入流
                    os.close();//关闭输出流
                    socket.close();//关闭soket
                    run_flag=false;//跳出死循环
                    System.out.println("TCP连接断开");  
                }                   
                buffer = null;
                System.gc();//垃圾回收
            } catch (IOException e) {
                e.printStackTrace();
            }   
        }
    }
}

}


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • ljheee ljheee 2016-09-08 02:45

    try {
    is.close();
    os.close();//关闭输出流
    socket.close();//关闭soket----------此处是客户端的套接字关闭。而服务器套接字接收到客户端连接之后ss.accept();,会尝试一直保持连接,但是此处的客户端的套接字关闭服务器端是不知道的,所有肯定会报socket closed异常,表明连接终端(客户端的套接字关闭了)。这是正常情况。
    如果不想看到,就把打印栈追踪信息那行删掉。

    点赞 评论 复制链接分享

相关推荐