安卓开发SOCKET编程中几种线程阻塞产生的原因与解决办法

本文详细介绍了在安卓socket编程中遇到的三种线程阻塞情况:DNS解析阻塞、连接阻塞和获取输入流阻塞。针对每种情况,文章提供了具体的异常状况描述和相应的解决办法,包括设置超时和使用特定方法避免长时间等待,以优化编程效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用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();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值