Сокет не закрывает серверную сторону при вызове socket.close () в клиентской JAVA - PullRequest
6 голосов
/ 22 июля 2010

У меня проблемы с сокетами в Java. У меня есть ServerSocket, который прослушивает с accept () и порождает потоки для каждого клиентского запроса. Связь между клиентами и сервером работает нормально. Я использую входной поток для чтения данных от клиентов на серверах, например:

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();
}

Серверные 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 ]

2 голосов
/ 22 июля 2010

Код сервера, который вы разместили, не проверяет -1.Так что это либо проблема, либо это не настоящий код, в этом случае вы должны опубликовать настоящий код для комментария.

РЕДАКТИРОВАТЬ Код, который у вас естьсообщение не ведет себя так, как вы описали.

1 голос
/ 22 июля 2010

Я не знаю, понимаю ли я вашу проблему, но я бы сказал, что это нормально, что сервер должен закрыть сокет.

На стороне сервера (в независимом потоке) у вас естьсокет прослушивания:

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 это может быть (взято из mockHttpServer в scala, поэтому могут быть некоторые ошибки, но процесс такой же):

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)
  • принимаемsocket (Object Socket, отправляемый socketServer.accept ())
  • клиентский сокет (как показано выше в примере)

Сервер открывает и закрывает слушающий и «принимающий» сокет, ине должно иметь никакого влияния на плохое управление клиентскими сокетами.

Тогда, если вы хотите, чтобы ваш сервер принимал несколько одновременных подключений, вы можете добавить ThreadPool для приема подключений и обработки запросов и ответов.

0 голосов
/ 06 мая 2011

Попробуйте это в своем коде клиента Android:

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

Это должно быть лучше; -)

...