Сейчас я немного играю с приложением Client-Server, чтобы общаться через Java-приложение с малиной pi, которая запускает серверное приложение.Java ServerSocket принимает только 2 соединения
Ну, я нашел проблему, и я не нашел возможного решения. Используя следующий код, я могу подключиться дважды к серверу, но после 2 подключений он не будет принимать никаких подключений. Например, я запускаю клиент в первый раз, и он отлично работает. Затем я закрываю клиент и запускаю его снова, и он снова работает. Но если я закрою его и начну в третий раз, он ничего не сделает. Сервер не будет принимать соединение. Я попробовал его с разными компьютерами в своей частной сети, но так и не получил 3-го соединения.
Вот код, который я бегу на сервере:
public class Receiver {
private final Logger logger = Logger.getLogger(this.getClass().getName());
private ServerSocket serverSocket;
private boolean isRunning;
public Receiver(int port) {
isRunning = true;
try {
serverSocket = new ServerSocket(port);
logger.log(Level.FINER, "start listening at port " + port);
logger.log(Level.FINER, "established successful.");
} catch (IOException e) {
logger.log(Level.SEVERE, "Error while opening socket:\n" + LogUtil.getStackTrace(e));
System.exit(1);
}
}
/**
* server starts to listen at the specific port
*/
public void listenServer() {
logger.log(Level.FINER, "Server is listening");
while (isRunning) {
try {
final Socket clientsocket = serverSocket.accept();
logger.log(Level.FINER, "Server accepted Connection from " + clientsocket.getInetAddress());
new Thread(new Runnable() {
@Override
public void run() {
handleConnection(clientsocket);
}
}).start();
} catch (IOException e) {
logger.log(Level.SEVERE, "Connection with Client failed.");
}
}
}
/**
* handles the given connection
*
* @param clientSocket
* the given client socket for this connection
*/
private void handleConnection(Socket clientSocket) {
ObjectInputStream instream = null;
ObjectOutputStream outstream = null;
try {
outstream = new ObjectOutputStream(clientSocket.getOutputStream());
instream = new ObjectInputStream(clientSocket.getInputStream());
final RequestProcessor processor = new RequestProcessor();
final InetAddress inetAdress = clientSocket.getInetAddress();
logger.log(Level.FINER, "handle connection from " + inetAdress);
Object inob;
while ((inob = instream.readObject()) != null) {
logger.log(Level.FINER, "received Object from " + inetAdress);
final ObjectOutputStream finalOutputStream = outstream;
final Object finalInob = inob;
new Thread() {
public void run() {
setPriority(MAX_PRIORITY);
Object outob;
try {
outob = processor.processObject(finalInob);
logger.log(Level.FINER, "send Respond to: " + inetAdress + " Error: " + (outob instanceof ErrorMessage));
finalOutputStream.writeObject(outob);
finalOutputStream.flush();
} catch (IOException e) {
logger.log(Level.SEVERE, "Connection closed to " + inetAdress);
}
}
}.start();
}
closeConnection(clientSocket, instream, outstream);
} catch (IOException e) {
logger.log(Level.SEVERE, "Connection closed to " + clientSocket.getInetAddress());
} catch (ClassNotFoundException e) {
logger.log(Level.SEVERE, "Connection closed to " + clientSocket.getInetAddress());
} finally {
closeConnection(clientSocket, instream, outstream);
}
}
/**
* closes InputStream, OutputStream and socket
*
* @param socket
* @param instream
* @param outstream
*/
private void closeConnection(Socket socket, InputStream instream, OutputStream outstream) {
this.isRunning = false;
if (instream != null) {
try {
instream.close();
} catch (IOException e) {
}
}
if (outstream != null) {
try {
outstream.close();
} catch (IOException e) {
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
logger.log(Level.FINER, "Connection was closed to client " + socket.getInetAddress());
}
/**
* closes all connections and ends the server
*/
public void endAllConnections() {
this.isRunning = false;
if (this.serverSocket != null)
try {
this.serverSocket.close();
} catch (IOException e) {
// do nothing
}
}
}
и вот клиентский код, который я использую для подключения к этому серверу:
public class SocketConnector implements IConnector {
private final Logger logger = Logger.getLogger(this.getClass().getName());
private Socket s;
private ObjectOutputStream oos;
private ObjectInputStream ois;
/**
* creates a new connection
*
* @param host
* given host
* @param port
* given port
*
* @throws UnknownHostException
* @throws IOException
*/
public SocketConnector(String host, int port) throws UnknownHostException, IOException {
logger.log(Level.FINER, "Establish connection to " + host + ":" + port);
s = new Socket(host, port);
oos = new ObjectOutputStream(s.getOutputStream());
ois = new ObjectInputStream(s.getInputStream());
}
// some methos which use oos and ois.
ли кто-то, может быть, знаете, почему сервер не принимает никаких подключений, когда 2 клиента подключены и отключены от него? Я googled много arround но не нашел адекватного ответа:/ В журнале сервера говорится, что он даже не принимает новое соединение.
Заранее спасибо :)
Работаете ли вы в Windows? Поскольку я думаю, что существует ограничение на стеки TCP/IP из 2-х соединений на хост, которые вы можете настроить, возившись с реестром Windows (или используя альтернативные имена хостов, такие как IP-адрес и имена хостов) –
Существуют и другие проблемы с этим кодом. 1. Потоки объектов должны быть созданы в методе run(), а не в конструкторе: в противном случае они выполняются в потоке accept(), потенциально блокируя его. 2. ObjectInputStream не возвращает null, если вы не написали нуль, поэтому цикл, пока он не возвращает нуль, не имеет смысла. Он выдает EOFException в конце потока: поймайте его и сломайте, когда вы его получите. @JasonSperske Существует ограничение на отставание TCP, но оно значительно выше 2. – EJP
Спасибо. Ватран решил главную проблему. Я снова посмотрю на это, чтобы следовать вашим советам, чтобы сделать его более чистым EJP :) – chf