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

时间:2010-07-21 20:39:51

标签: java sockets multithreading inputstream

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

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

我的问题是,如果我从客户端调用socket.close(),则bytes = 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

3 个答案:

答案 0 :(得分:2)

您发布的服务器代码不会检查-1。所以这是问题还是不是真正的代码,在这种情况下你应该发布真正的代码进行评论。

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

答案 1 :(得分:1)

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

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

ServerSocket socketServeur = new ServerSocket(port);

然后可能(在相同的线程中,如果它是一个小服务器)接受传入连接的循环(没有异常管理,可能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个“插座”:

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

服务器打开和关闭侦听和“接受”套接字,并且应该不会影响错误的客户端套接字管理。

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

答案 2 :(得分:0)

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

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

应该更好; - )