現在我正在與客戶端 - 服務器應用程序進行一些小規模的工作,例如通過java應用程序與運行服務器應用程序的樹莓派進行通信。Java ServerSocket只接受2個連接
那麼,我發現了一個問題,我沒有找到一個可能的解決方案。使用下面的代碼,我可以連接兩次到服務器,但2次連接後它不會再接受任何連接。例如,我第一次啓動客戶端,它可以很好地工作。然後我關閉客戶端並重新啓動它並再次運行。但是如果我關閉它並且第三次啓動它,它就什麼都不會做。服務器不會接受連接。我在我的私人網絡中使用不同的個人電腦進行了嘗試,但從未獲得第三個連接。
這裏是我的服務器上運行的代碼:
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個客戶端連接並斷開連接時,服務器不會再接受任何連接?我GOOGLE了很多,但沒有找到一個合適的答案:/ 服務器日誌說,它甚至不接受新的連接。
感謝提前:)
你在Windows中運行嗎?因爲我認爲每個主機有2個連接的TCP/IP堆棧限制,您可以通過與Windows註冊表(或使用其他主機名稱,如IP地址和主機名)混合來調整 –
此代碼還有其他問題。 1.對象流應該在run()方法中創建,而不是在構造函數中創建:否則它們將在accept()線程中執行,可能會阻塞它。 2.除非您寫入null,否則ObjectInputStream不會返回null,因此在不返回null的情況下循環無效。它在流結束時拋出EOFException:捕獲該錯誤,並在獲取時拋棄。 @JasonSperske有一個TCP積壓限制,但它比2高得多。 – EJP
謝謝。 Vutran解決了主要問題。我會再看看它,按照您的建議,使其更清潔EJP :) – chf