Как правильно закрыть сокет, а затем снова открыть его? - PullRequest
7 голосов
/ 11 декабря 2011

Я занимаюсь разработкой игры для своего класса, и она выполнена на 99%.Однако я понял, что есть проблема: если сервер и клиент отключаются, и клиент пытается восстановить соединение (и сервер снова работает и работает нормально), клиент не устанавливает новое соединение.

Сервер и клиент являются многопоточными.Если я отправлю клиенту сообщение Kick, то произойдет, если клиент закроет сокет.Если я переподключаюсь, я получаю SocketException: сокет закрытым, даже если при каждом нажатии соединения создается новый Клиент, который в основном является просто классом, который создает сокет и соединяется с сервером потоком get / send.

Как вы думаете, есть что-то, что я делаю нелогично?Это похоже на попытку использовать старые сокет и клиент, которые были сконструированы, но если я делаю несколько вызовов println, я вижу, что он создает новый, и они находятся в разных местах памяти.

Спасибо!

Ответы [ 2 ]

9 голосов
/ 11 декабря 2011

После закрытия сокета вы не сможете повторно использовать его для обмена другими данными между классами Server и Client.Из Java Socket API , около close() описание метода:

Любой поток, в настоящее время заблокированный в операции ввода-вывода на этом сокете, вызовет исключение SocketException.

После закрытия сокета он становится недоступным для дальнейшего использования в сети (т. Е. Не может быть повторно подключен или восстановлен).Новый сокет должен быть создан.

Закрытие этого сокета также закроет сокет InputStream и OutputStream.

Если с этим сокетом связан канал, канал также закрывается.

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

2 голосов
/ 25 мая 2016

Это может быть легко!Я сделал эту программу (на стороне сервера):

import java.net.ServerSocket;
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;

public class Host{
    public static void main(String[] args) throws Exception{
        while(true){
            ServerSocket ss = new ServerSocket(1300);
            Socket s = ss.accept();
            DataInputStream din = new DataInputStream(s.getInputStream());
            String msgin = din.readUTF();
            System.out.println(msgin);
            ss.close();
            s.close();
            din.close();
        }
    }
}

На стороне клиента:

import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;

public class Client{
    public static void main(String[] args) throws Exception{
        while(true){
            Socket s = new Socket("localhost", 1300);
            DataOutputStream dout = new DataOutputStream(s.getOutputStream());
            dout.writeUTF("hello");
            s.close();
            dout.close();
        }
    }
}

Это работает, потому что вы можете объявить тонны сокетов с тем же ServerSocket, так, например, это работаеттоже:

ServerSocket ss = new ServerSocket(1300);
Socket a = ss.accept();
Socket b = ss.accept();
Socket c = ss.accept();

и у вас есть 3 сокета ... Помните: Java ожидает подключения клиента, когда вы объявляете сокет!Код:

Клиент:

import java.net.Socket;

public class client {
    public static void main(String[] args) throws Exception{
        Socket a = new Socket("localhost", 1300);
        Thread.sleep(3000);
        Socket b = new Socket("localhost", 1300);
        Thread.sleep(3000);
        Socket c = new Socket("localhost", 1300);
        Thread.sleep(3000);
        a.close();
        b.close();
        c.close();
    }
}

Сервер:

import java.net.ServerSocket;
import java.net.Socket;

public class server {
    public static void main(String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(1300);
        System.err.println("Listening...");
        Socket a = ss.accept();
        System.err.println("1");
        Socket b = ss.accept();
        System.err.println("2");
        Socket c = ss.accept();
        System.err.println("3");
    }
}
...