Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何终止由于Socket.accept()而阻塞时间过长的线程?_Java_Multithreading_Sockets_Runnable_Blocking - Fatal编程技术网

Java 如何终止由于Socket.accept()而阻塞时间过长的线程?

Java 如何终止由于Socket.accept()而阻塞时间过长的线程?,java,multithreading,sockets,runnable,blocking,Java,Multithreading,Sockets,Runnable,Blocking,因此,我有一个服务器,可以同时为多个客户端提供服务。每当客户机连接时,服务器将创建一个新的从机,将该从机的IP/端口发送给客户机,然后客户机将使用该从机 但是,如果客户机收到从机地址,则不执行任何操作(或退出)(编辑:这意味着客户机和服务器已连接,但客户机不执行任何操作,因为例如用户去吃午饭)slaveSocket.accept()会导致从机线程永远运行,这是浪费 我希望从线程在等待slaveSocket.accept()30秒后退出。由于slaveSocket.accept()正在阻塞,因此我

因此,我有一个服务器,可以同时为多个客户端提供服务。每当客户机连接时,服务器将创建一个新的从机,将该从机的IP/端口发送给客户机,然后客户机将使用该从机


但是,如果客户机收到从机地址,则不执行任何操作(或退出)(编辑:这意味着客户机和服务器已连接,但客户机不执行任何操作,因为例如用户去吃午饭)
slaveSocket.accept()
会导致从机线程永远运行,这是浪费

我希望从线程在等待
slaveSocket.accept()
30秒后退出。由于
slaveSocket.accept()
正在阻塞,因此我无法从
void run()
内部执行此操作

解决这个问题的正确、干净的方法是什么?多谢各位

编辑1:服务器套接字被传递到从机,因为客户端可以有多个进程连接到该从机。因此,它不只是执行一个功能。

非阻塞I/O: 看看返回
未来
的方法。然后
未来的
有一个可以满足您要求的功能

注意:您可以阅读一篇文章

然后getter将返回一个
AsynchronousSocketChannel
,它可以通过与工作线程中的阻塞方法一起使用的相应and方法转换回阻塞

阻塞I/O: 我认为您实际上指的是如何实现一个服务器,该服务器通过阻塞I/O顺序地接受客户机并并行地为客户机提供服务。如果是这种情况,那么您可以查看以下示例:

public class Slave implements Runnable {
   public ServerSocket slaveSocket;

   public Slave(ServerSocket sk) {socket = sk;}

   @Override
   public void run() {
      Socket client = slaveSocket.accept(); // slave will wait to serve a client
      // more code...

      Socket clientPart2 = slaveSocket.accept();
      // more code...
   }
}

public class Server {
   public static void main(String[] args) {
       // for example only, incomplete code
       ServerSocket serverSocket = new ServerSocket(0); // a client connect to 8088
       Slave slave = new Slave(serverSocket);
       new Thread(slave).start(); // slave serve the current client, the server wait for new client

       // send new slave's port to client ... 
   }
}
非阻塞I/O: 看看返回
未来
的方法。然后
未来的
有一个可以满足您要求的功能

注意:您可以阅读一篇文章

然后getter将返回一个
AsynchronousSocketChannel
,它可以通过与工作线程中的阻塞方法一起使用的相应and方法转换回阻塞

阻塞I/O: 我认为您实际上指的是如何实现一个服务器,该服务器通过阻塞I/O顺序地接受客户机并并行地为客户机提供服务。如果是这种情况,那么您可以查看以下示例:

public class Slave implements Runnable {
   public ServerSocket slaveSocket;

   public Slave(ServerSocket sk) {socket = sk;}

   @Override
   public void run() {
      Socket client = slaveSocket.accept(); // slave will wait to serve a client
      // more code...

      Socket clientPart2 = slaveSocket.accept();
      // more code...
   }
}

public class Server {
   public static void main(String[] args) {
       // for example only, incomplete code
       ServerSocket serverSocket = new ServerSocket(0); // a client connect to 8088
       Slave slave = new Slave(serverSocket);
       new Thread(slave).start(); // slave serve the current client, the server wait for new client

       // send new slave's port to client ... 
   }
}

如果使用SetSocket设置超时,并且没有客户端连接,ServerSocket.accept将引发异常。您可以捕获此异常

要设置30秒的超时,请使用:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;

public class Main {

    public static class Worker implements Runnable {
        private final Socket sck;
        private OutputStream os;
        private InputStream is;

        public Worker(final Socket sck) {
            this.sck = Objects.requireNonNull(sck);
        }

        @Override
        public void run() {
            try {
                os = sck.getOutputStream();
                is = sck.getInputStream();

                //ALL the work with the client goes here, unless you need more than one connections with him.
            }
            catch (final IOException iox) {
                System.err.println(iox);
            }
            finally {
                try { is.close(); } catch (final IOException | RuntimeException x) {}
                try { os.close(); } catch (final IOException | RuntimeException x) {}
                try { sck.close(); } catch (final IOException | RuntimeException x) {}
            }
        }
    }

    public static void main(final String[] args) {
        ServerSocket srv = null;
        try {
            srv = new ServerSocket(8088);
            while (true)
                new Thread(new Worker(srv.accept())).start();
        }
        catch (final IOException iox) {
            System.err.println(iox);
        }
        finally {
            try { srv.close(); } catch (final IOException | RuntimeException x) {}
        }
    }
}

如果使用SetSocket设置超时,并且没有客户端连接,ServerSocket.accept将引发异常。您可以捕获此异常

要设置30秒的超时,请使用:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;

public class Main {

    public static class Worker implements Runnable {
        private final Socket sck;
        private OutputStream os;
        private InputStream is;

        public Worker(final Socket sck) {
            this.sck = Objects.requireNonNull(sck);
        }

        @Override
        public void run() {
            try {
                os = sck.getOutputStream();
                is = sck.getInputStream();

                //ALL the work with the client goes here, unless you need more than one connections with him.
            }
            catch (final IOException iox) {
                System.err.println(iox);
            }
            finally {
                try { is.close(); } catch (final IOException | RuntimeException x) {}
                try { os.close(); } catch (final IOException | RuntimeException x) {}
                try { sck.close(); } catch (final IOException | RuntimeException x) {}
            }
        }
    }

    public static void main(final String[] args) {
        ServerSocket srv = null;
        try {
            srv = new ServerSocket(8088);
            while (true)
                new Thread(new Worker(srv.accept())).start();
        }
        catch (final IOException iox) {
            System.err.println(iox);
        }
        finally {
            try { srv.close(); } catch (final IOException | RuntimeException x) {}
        }
    }
}

,特别是抛出SocketTimeoutException的原因。每当客户端连接时,服务器将创建一个新的从服务器。。。但是正如我所看到的,您将
ServerSocket
传递给
从线程类。。。你想达到什么目标?我这样问是因为工作线程(或
从线程
类)通常用于服务于客户机。因此,您应该(通常至少)将一个
Socket
实例传递给
Slave
类,以便为单个(已接受的)客户端提供服务器。此外,客户端在第一次连接时已经知道服务器的IP和端口。你不需要把它寄给他,至少在这种情况下我是这么认为的。您已经可以在
从属
类中使用名为
客户端
套接字
。无需创建另一个套接字。也不需要向他发送IP+端口,因为客户端已经知道它首先要连接。除非你向他发送另一台服务器的IP+端口。这就是为什么(底线)我问你想要实现什么。“但是,如果客户机收到从机地址,那么什么也不做(或退出)…”我无法解析或理解这句话。可能重写?@gthanop客户端包含多个进程,每个进程都需要单独与从属进程一起工作。因此,从属服务器不能使用与服务器相同的套接字,因为服务器仍然需要接受新来的客户端(或者我可以使用相同的套接字吗?我还没有尝试过),特别是为什么会抛出SocketTimeoutException。每当客户端连接时,服务器都会创建一个新的从属服务器。。。但是正如我所看到的,您将
ServerSocket
传递给
从线程类。。。你想达到什么目标?我这样问是因为工作线程(或
从线程
类)通常用于服务于客户机。因此,您应该(通常至少)将一个
Socket
实例传递给
Slave
类,以便为单个(已接受的)客户端提供服务器。此外,客户端在第一次连接时已经知道服务器的IP和端口。你不需要把它寄给他,至少在这种情况下我是这么认为的。您已经可以在
从属
类中使用名为
客户端
套接字
。无需创建另一个套接字。也不需要向他发送IP+端口,因为客户端已经知道它首先要连接。除非你向他发送另一台服务器的IP+端口。这就是为什么(底线)我问你想要实现什么。“但是,如果客户机收到从机地址,那么什么也不做(或退出)…”我无法解析或理解这句话。可能重写?@gthanop客户端包含多个进程,每个进程都需要单独与从属进程一起工作。所以从服务器不能使用与服务器相同的套接字,因为服务器仍然需要接受新的客户机(或者我可以使用相同的套接字吗?我没有尝试过)哈哈。我不知道它有那么简单+哇,那太简单了,没什么不方便的。谢谢你。我不知道有那么简单+哇,那太简单了,没什么不方便的。谢谢你。我试过了,发现客户端可能需要建立多个连接。所以这还不够谢谢你。我试过了,发现客户可能需要