草庐IT

Android - 套接字连接,即使它不能

coder 2023-12-15 原文

首先,我知道你在想什么,这是一个奇怪的问题,似乎这不可能是真的,但我想谈谈这个……

该项目是一个通过套接字发送字节数组并从套接字接收数据的项目。我目前正在从事保护工作。我想确保用户知道套接字何时因任何原因无法连接...您可以查看下面的连接代码。

所以我有一个 android 应用程序,它连接到世界其他地方办公室的 Windows Server 计算机上的可执行文件。套接字通过常用的 IP 地址和端口号连接。

我正在使用 Android 5.0 (lollipop) 手机测试该应用...

现在够无聊的东西了: 如果我关闭服务器并完全关闭它并在 wi-fi 上测试它,那么套接字就会失败——这是正确的。它无法连接,并且会抛出 SocketException。这很好并且按预期工作。现在,如果我关闭 wi-fi 并使用移动数据(我在阳光明媚的英国使用 o2!),那么问题就出现了,使用相同的代码,服务器仍然关闭,我不会抛出 SocketException,相反,代码简单认为它已连接到套接字上。连接线程在下面。

Thread StartConnection = new Thread()
        {
            @Override
            public void run()
            {

                int dstPort = 10600;

                socket = new Socket();
                try
                {
                    ipaddress = InetAddress.getByName(dstName);
                }
                catch (UnknownHostException uhe)
                {
                    uhe.printStackTrace();
                }

                j = new InetSocketAddress(IPString , dstPort);

                try
                {
                        socket.setKeepAlive(true);
                        socket.setReuseAddress(true);
                        socket.setTcpNoDelay(true);
                        socket.setSoTimeout(5000);
                        socket.connect(j, 5000);
                        connected = true;
                        outputstream = socket.getOutputStream();
                        DataThread();
                        SocketError = false;
                }
                catch (SocketException se)
                {
                    se.printStackTrace();
                }
                catch (IllegalArgumentException iae)
                {
                    iae.printStackTrace();
                }
                catch (IOException ioe)
                {
                    ioe.printStackTrace();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        };
        StartConnection.start();

socket.connect(j, 5000); 

工作正常,没有套接字错误。也没有超时。

outputstream = socket.getOutputStream(); 

也有效。我得到“java.net.PlainSocketImpl$PlainSocketOutputStream@48e6f6e”的结果,这也很好。

socket.getInputStream() 返回“java.net.PlainSocketImpl$PlainSocketInputStream@1ea305a5”

最佳答案

这很有趣。我一直在测试并且可以复制您描述的行为。

首先,这里投票最高的答案对 Java Socket API 进行了很好的讨论:

Java socket API: How to tell if a connection has been closed?

据此,我想知道尝试从套接字读取一个字节是否允许我们检查它是否真的打开

// Endpoint that does not exist
Socket socket = new Socket("1.2.3.4", 1234);
InputStream tmpIn = socket.getInputStream();
int result = tmpIn.read();
Log.i("SocketTest", "read() result: " + result);

在端点无效的情况下,我发现对 read() 的调用在大约 10 秒后返回 -1。

在 IP 和端口上有监听器的情况下,对 read() 的调用似乎会无限期地阻塞,直到发生某些事情,例如实际从服务器接收数据,或丢失互联网连接等

基于这种差异,我将此测试包装到一个新类中:

public class VerifiedSocket extends Socket {

    public VerifiedSocket(String ip, int port, int millisecondTimeout) throws UnknownHostException, IOException{
        super(ip,port);

        ReadThread tryRead = new ReadThread();      
        tryRead.start();
        try {
            tryRead.join(millisecondTimeout);
        } catch (InterruptedException e) {
        }
        if(tryRead.getReadValue()==-1){
            // We read -1 so assume endpoint invalid
            throw new IOException("Endpoint is invalid");
        }       
    }

    private class ReadThread extends Thread{
        private int readValue = 512; // Impossible byte value

        @Override
        public void run(){              
            try {
                InputStream input = getInputStream();
                readValue = input.read();
            } catch (IOException e) {                   
            }               
        }

        public int getReadValue(){
            return readValue;
        }
    }       
}

然后测试如下:

try {
    VerifiedSocket socket = new VerifiedSocket("1.2.3.4", 1234, 20000);
    Log.i("SocketTest", "Endpoint is valid");
    socket.close();
} catch (UnknownHostException e) {      
    Log.e("SocketTest", e.getLocalizedMessage());
} catch (IOException e) {       
    Log.e("SocketTest", e.getLocalizedMessage());
}

如果我在 Wifi 上使用无效端点,VerifiedSocket 的构造函数会抛出超时异常。如果我在移动数据上使用无效端点,它会抛出带有“端点无效”消息的 IOException。不完美,但希望对您有所帮助。

关于Android - 套接字连接,即使它不能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28676238/

有关Android - 套接字连接,即使它不能的更多相关文章

  1. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  2. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  3. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  4. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  5. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  6. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  7. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  8. 即使安装了 gem,Ruby 也找不到所需的库 - 2

    我花了几天时间尝试安装ruby​​1.9.2并让它与gems一起工作:-/我最终放弃了我的MacOSX10.6机器,下面是我的Ubuntu机器上的当前状态。任何建议将不胜感激!#rubytest.rb:29:in`require':nosuchfiletoload--mongo(LoadError)from:29:in`require'fromtest.rb:1:in`'#cattest.rbrequire'mongo'db=Mongo::Connection.new.db("mydb")#gemwhichmongo/usr/local/rvm/gems/ruby-1.9.2-p0/g

  9. ruby-on-rails - Ruby 的 'open_uri' 是否在读取或失败后可靠地关闭套接字? - 2

    一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我

  10. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

随机推荐