Java非阻塞NIO网络编程连接超时的处理

在NIO网络编程中,需要使用如下语句来完成客户端对服务器的连接:

			Selector selector = Selector.open();
			InetSocketAddress isa = new InetSocketAddress(host, port);
			// 调用open静态方法创建连接到指定主机的SocketChannel
			SocketChannel sc = SocketChannel.open(isa);

但却没有相关方法来设置超时参数,这就导致在调用open()方法时,如果连接不上服务器,那么此方法就会长时间阻塞(试了一下,大约阻塞了1-2分钟才抛出SocketTimeoutException),为了解决这个问题,我们可以在调用open()方法前,启动一个定时器,这个定时器会在指定的时间内检查是否已连接成功,这个指定的时间也就是我们希望设置的连接超时时间,当检查已连接上服务器时,提示用户已连接成功;若没有连接上,可在代码中抛出SocketTimeoutException,并提示用户连接超时。代码如下:

package com.test.thread;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Handler;
import android.os.Message;

public class NetworkNIOThread implements Runnable
{

	// 定义处理编码和解码的字符集
	public static final Charset CHAR_SET = Charset.forName("GBK");

	// 定义检测SocketChannel的Selector对象
	private Selector selector;

	// 客户端SocketChannel
	private SocketChannel sc;

	private Handler handler;
	private String host;
	private int port;

	public NetworkNIOThread(Handler handler, String host, int port)
			throws IOException
	{
		this.handler = handler;
		this.host = host;
		this.port = port;
	}

	@Override
	public void run()
	{
		connect();
	}

	public void connect()
	{
		try
		{
			selector = Selector.open();
			InetSocketAddress isa = new InetSocketAddress(host, port);
			//10秒连接超时
			new Timer().schedule(tt, 10000);
			// 调用open静态方法创建连接到指定主机的SocketChannel
			sc = SocketChannel.open(isa);
			// 设置该sc以非阻塞方式工作
			sc.configureBlocking(false);
			// 将Socketchannel对象注册到指定Selector
			sc.register(selector, SelectionKey.OP_READ);
			Message msg = new Message();
			msg.what = 0;
			msg.obj = sc;
			handler.sendMessage(msg); // 连接成功
			new Thread(new NIOReceiveThread(selector, handler)).start();

		}
		catch (IOException e)
		{
			e.printStackTrace();
			handler.sendEmptyMessage(-1); // IO异常
		}

	}
	
	TimerTask tt = new TimerTask()
	{

		@Override
		public void run()
		{
			if (sc == null || !sc.isConnected())
			{
				try
				{
					throw new SocketTimeoutException("连接超时");
				}
				catch (SocketTimeoutException e)
				{
					e.printStackTrace();
					handler.sendEmptyMessage(-6); // 连接超时
				}
			}
		}
		
	};
}


你可能感兴趣的:(网络,网络编程,socket,nio)