Socket.connect(InetSocketAddress, timeout) 不起作用,而 new Socket(InetAddress, port) 起作用

发布于 2025-01-10 05:39:10 字数 2554 浏览 0 评论 0原文

我偶然发现了一些非常奇特的东西。当我尝试在对等应用程序中连接到 LAN 服务器时,socket.connect 似乎不起作用,而 new Socket 却起作用。 提供的 InetAddress 是链接本地 IPV6,但这不应该(?)成为此错误的一个因素。 这是有效的代码:

    @Override
    public void createUserSocket() throws IOException, InvalidPortValueException {
        if (!portIsValid()) throw new InvalidPortValueException();
        shutdown();
        Log.d(TAG + ".createUserSocket", "TRYING TO CONNECT TO " + address.getHostAddress() + " : " + port);
        currentUserSocket = new SocketAdapter(address, port);
        currentUserSocket.setTimeout(SO_TIMEOUT);
        Log.d(TAG + ".createUserSocket", "connected to " + currentUserSocket.log());
    }

这是无效的代码:

    @Override
    public void createUserSocket() throws IOException, InvalidPortValueException {
        if (!portIsValid()) throw new InvalidPortValueException();
        shutdown();
        currentUserSocket = new SocketAdapter();
        InetSocketAddress soAddr = new InetSocketAddress(address, port); 
        Log.e(TAG + ".createUserSocket", "TRYING TO CONNECT TO " + soAddr.getAddress().getHostAddress() + " " + soAddr.getPort() + " with timeout " + SO_TIMEOUT);
        currentUserSocket.connect(soAddr, SO_TIMEOUT);
        Log.d(TAG + ".createUserSocket", "connected to " + currentUserSocket.log());
    }

值得注意的是,SocketAdapter 只是 Socket 类的包装类,并且不执行任何有趣的操作。 SocketAdapter 的相关代码如下。

SO_TIMEOUT 是一个变量,指定超时时间(以毫秒为单位),地址 &两个块的端口保持相同:

private static final int SO_TIMEOUT = 2000;
private final InetAddress address;
private final int port;

第一个示例按预期工作,连接并且一切正常。 第二个例子不起作用,而是永远阻塞。

我得到了地址&连接外部的端口;但是,正如我之前所说,第一个示例有效,而第二个示例则无效,在 .connect 方法中永远阻塞。 我很感激对这种行为的任何见解,因为这是我的应用程序效率的关键部分。先感谢您!

请注意,我测试的两个设备分别是 API 26 和 30。两款都是 A 系列三星手机(不同代)。

SocketAdapter

    private Socket socket;

    public SocketAdapter() {}

    public SocketAdapter(Socket s) {
        socket = s;
    }

    public SocketAdapter(InetAddress address, int port) throws IOException {
        socket = StaticSocketFactory.createSocket(address, port);
    }

    public InetAddress getInetAddress() {
        return socket.getInetAddress();
    }

    public void connect(SocketAddress addr, int soTimeout) throws IOException {
        socket.connect(addr, soTimeout);
    }

静态SocketFactory

    static Socket createSocket(InetAddress addr, int port) throws IOException {
        return new Socket(addr, port);
    }

I've stumbled upon something very peculiar. When I'm trying to connect to a LAN server in my peer to peer application, it looks like socket.connect doesn't work, while the new Socket does.
The InetAddress provided are link-local IPV6s, however that should(?) not be a factor in this bug.
Here's the code that works:

    @Override
    public void createUserSocket() throws IOException, InvalidPortValueException {
        if (!portIsValid()) throw new InvalidPortValueException();
        shutdown();
        Log.d(TAG + ".createUserSocket", "TRYING TO CONNECT TO " + address.getHostAddress() + " : " + port);
        currentUserSocket = new SocketAdapter(address, port);
        currentUserSocket.setTimeout(SO_TIMEOUT);
        Log.d(TAG + ".createUserSocket", "connected to " + currentUserSocket.log());
    }

Here's the code that doesn't:

    @Override
    public void createUserSocket() throws IOException, InvalidPortValueException {
        if (!portIsValid()) throw new InvalidPortValueException();
        shutdown();
        currentUserSocket = new SocketAdapter();
        InetSocketAddress soAddr = new InetSocketAddress(address, port); 
        Log.e(TAG + ".createUserSocket", "TRYING TO CONNECT TO " + soAddr.getAddress().getHostAddress() + " " + soAddr.getPort() + " with timeout " + SO_TIMEOUT);
        currentUserSocket.connect(soAddr, SO_TIMEOUT);
        Log.d(TAG + ".createUserSocket", "connected to " + currentUserSocket.log());
    }

It's worthwhile to note SocketAdapter is just a wrapper class for the Socket class, and doesn't do any funny stuff. The relevant bits of code for SocketAdapter are below.

SO_TIMEOUT is a variable specifying timeout in millisecond time, and address & port remain the same from the two blocks:

private static final int SO_TIMEOUT = 2000;
private final InetAddress address;
private final int port;

The first example works as expected, connects and everything's OK.
The second example doesn't work, and instead blocks forever.

I get the address & port to connect to externally; however, as I said before, the first example works, while the second example doesn't, blocking forever in the .connect method.
I'd appreciate any insight for this sort of behaviour, since this is a critical part for the efficiency of my application. Thank you in advance!

Note, that the two devices I'm testing with, are API 26 and 30 respectively. Both are A-Series SAMSUNG phones (from different generations).

SocketAdapter

    private Socket socket;

    public SocketAdapter() {}

    public SocketAdapter(Socket s) {
        socket = s;
    }

    public SocketAdapter(InetAddress address, int port) throws IOException {
        socket = StaticSocketFactory.createSocket(address, port);
    }

    public InetAddress getInetAddress() {
        return socket.getInetAddress();
    }

    public void connect(SocketAddress addr, int soTimeout) throws IOException {
        socket.connect(addr, soTimeout);
    }

StaticSocketFactory

    static Socket createSocket(InetAddress addr, int port) throws IOException {
        return new Socket(addr, port);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不打扰别人 2025-01-17 05:39:10

我不明白你如何尝试创建套接字,但如果你想使用套接字,你必须这样做:

  1. 定义一个服务器套接字

    ServerSocket serverSocket = new ServerSocket(8080);

  2. 然后就可以等待客户端连接了

Socket socket = serverSocket.accept();

  1. 如果您的客户端发送数据,则创建一个使用 BufferedReader 读取 http 请求的函数。如果您想向客户端发送数据,我邀请您使用 HttpURLConnection (https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html

我邀请您为连接到您的服务器的每个客户端创建一个线程。并且不要忘记关闭套接字。

I don't understand how you try to create socket but if you want use socket you have to do it this way :

  1. Defind a serversocket

    ServerSocket serverSocket = new ServerSocket(8080);

  2. Then you can wait for a client to connect

Socket socket = serverSocket.accept();

  1. If your client send data then make a function that read http request with BufferedReader. If you want send data to the client I invite you to use HttpURLConnection (https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html)

I invite you to create a thread for each client that connect to your server. And don't forget to close your socket.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文