在使用socket编程中,有几种情况会使线程产生阻塞。
1、解析DNS阻塞
当需要把一个域名解析为IP地址的时候,可用使用以下语句来获得。使用下面API的时候,如果当前环境没有网络,或者网络异常,将会使得解析失败,getByName方法会抛出异常,但是抛出异常的时间大约在三四分钟以后,时间太长。
InetAddress add = InetAddress.getByName(hostname);
String ip=add.getHostAddress();
解决方法(转载):
package com.liang.client;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 自定义解析DNS服务器类,解决断网或异常情况下抛出 UnknownHostException时间太长的问题。
* @author Liang
* 用法:
* 1、在需要解析的线程中创建DNSLookupThread线程对象
* DNSLookupThread dnsquery=new DNSLookupThread("liangruimi.vicp.net");
* 2、开启线程
* dnsquery.start();
* 3、设置连接超时时间,这里等待线程运行2s,即如果解析域名时间超过2s,则读取结果,解析成功,返回的是IP地址,失败返回的为空
* dnsquery.join(2000);
* 4、得到解析结果,如果为NULL,则表示解析失败
* String ip = dnsquery.getIP();
*/
public class DNSLookupThread extends Thread {
private InetAddress addr;
private String hostname;
public DNSLookupThread(String hostname) {
this.hostname = hostname;
}
public void run() {
try {
InetAddress add = InetAddress.getByName(hostname);
set(add);
} catch (UnknownHostException e) {
}
}
private synchronized void set(InetAddress addr) {
this.addr = addr;
}
public synchronized String getIP() {
if (null != this.addr) {
return addr.getHostAddress();
}
return null;
}
}
2、链接阻塞
当需要与服务器创建连接的时候,可以用以下方法来创建连接。使用如下方法构造socket对象会引起线程的长时间阻塞。因为如果端口无法连接,那么抛出异常的时间会很长,整个过程与上诉阻塞类似,大约需要三四分钟。因此不建议用此方法来创建socket。
socket = new Socket(ipaAddress, 38134);//创建一个链接地址为IPAddress,端口38134为的对象。
解决方法:使用socket的Socket.connect(SocketAddress remoteAddr, int timeout)方法。
socket = new Socket();//创建一个没有连接的socket对象
SocketAddress saddress = new InetSocketAddress(ip, 38134);//设置连接地址与端口
socket.connect(saddress, 10000);//第二个参数设置连接超时时间,这里设置为10s。
if (socket.isConnected()) {
Log.i("liang", "socket已连接");//判断连接是否成功。
}
3、获取输入流阻塞:
当需要获取socket中输入流信息的时候可用使用以下方法,使用InputStreamReader方法将socket中InputStream流转换为Reader类,并使用Reader类中的readLine方法获得信息。但是当调用readLine()方法的时候,如果输入流中没有任何数据的时候将一直等待,产生线程阻塞。
BufferedReader socketin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String socketinMessage = socketin.readLine();
解决方法:
在上述代码前设置超时时间
socket.setSoTimeout(50000);//此方法可以设置读取输入流超时时间,这里设置为5s
BufferedReader socketin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String socketinMessage = socketin.readLine();