在客户端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();
应该更好;-)