在客户端JAVA中调用socket.close()时,套接字未关闭服务器端

我在java中遇到套接字问题。 我有一个正在使用accept()监听的ServerSocket ,并为每个客户端请求生成线程。 客户端和服务器之间的通信正常。 我正在使用输入流从serverthreads中的客户端读取数据,例如:

 inputStream = mySocket.getInputStream(); bytes = inputStream.read(buffer); 

我的问题是,如果我从客户端调用socket.close(),则对bytes = inputStream.read(buffer);的阻塞调用没有任何反应bytes = inputStream.read(buffer); ,它继续阻止。 但是如果我从服务器关闭套接字,然后是inputStream.read(buffer);它就有效inputStream.read(buffer); 客户端返回“-1”。

SERVER-MAINTHREAD:

 //SERVER MAIN THREAD, SPAWNS CLIENT THREADS ServerSocket serverSocket = new ServerSocket(SERVERPORT); while (listening){ new ServerThread(serverSocket.accept(), monitor).start(); } 

SERVER-CLIENTTHREADS:

 public class ServerThread extends Thread{ public ServerThread(Socket socket, Monitor monitor) { this.socket = socket; this.monitor = monitor; } public void run(){ byte[] buffer = new byte[1024]; int bytes; //Listen while(true){ try { InputStream inputStream = socket.getInputStream(); monitor.doStuffWithOtherThreads(Object myObject); bytes = inputStream.read(buffer); //Problem if (bytes == -1){ System.out.println("breaks"); break; } byte[] readBuf = (byte[]) buffer; String readMessage = new String(readBuf, 0, bytes); System.out.println(readMessage); System.out.println(bytes); } catch (IOException e) { System.out.println("Connection closed"); break; } } } 

客户:

 InetAddress serverAddr = InetAddress.getByName("serverhostname"); socket = new Socket(serverAddr, PORT); socket.close(); //Close the socket connection from client. Nothing happens in the serverthread 

您发布的服务器代码不检查-1。 因此,无论是问题还是不是真正的代码,在这种情况下,您应该发布真实的代码以供评论。

编辑您发布的代码不符合您的描述。

我不知道我是否理解你的问题,但我会说服务器关闭套接字是正常的。

在服务器端(在一个独立的线程中),你有一个监听套接字:

 ServerSocket socketServeur = new ServerSocket(port); 

然后可能(在同一个线程中,如果它是一个servlets器)接受传入连接的循环(没有exception管理,可能socket.close在finally块中):

 while (! askedToClose) { Socket socket = socketServeur.accept(); doSomethingWithRequest(socket); socket.close(); } 

在客户端,您有:

 Socket clientSocket = new Socket(); clientSocket.connect(new InetSocketAddress(port)); OutputStream output = clientSocket.getOutputStream(); // send something to server InputStream input = clientSocket.getInputStream(); // will block until data is available // reading response 

服务器应该知道它何时到达请求的末尾。 例如在http中它可能是(从scala中的mockHttpServer获取,因此可能存在一些错误,但过程是相同的):

 void doSomethingWithRequest(Socket socket) { BufferedReader inputReader = new BufferedReader(new InputStreamReader(socket.getInputStream)); StreamWriter outputWriter = new OutputStreamWriter(socket.getOutputStream); StringBuilder requestBuilder = new StringBuilder(); do { requestBuilder.append(inputReader.read().toChar()); } while (!requestBuilder.toString().endsWith("\r\n\r\n")); saveUri(getUriFromRequest(requestBuilder.toString())); outputWriter.write("HTTP/1.1 200 OK\r\n\r\n"); outputWriter.flush(); inputReader.close(); outputWriter.close(); } 

编辑:我读了添加的代码,我仍然没有得到它:

  • 你调用Socket.close(),但这个方法不是静态的
  • 你永远在“服务器”循环
  • 我的印象是你为客户端和服务器使用相同的套接字

你有3个“sockets”:

  • 监听套接字(对象ServerSocket)
  • accept socket(socketServer.accept()发送的对象套接字)
  • 客户端套接字(如上例所示)

服务器打开和关闭监听和“接受”套接字,并且应该没有坏客户端套接字管理的影响。

然后,如果您希望服务器接受多个并发连接,则可以添加ThreadPool以接受连接并处理请求和响应。

在您的Android客户端代码中尝试此操作:

 socket.shutdownOutput(); socket.close(); 

应该更好;-)