Я пытаюсь обработать несколько подключений к одному и тому же порту моего сервера.Я делаю это путем создания экземпляра Object и передачи его в конструктор для другого класса, который реализует Runnable.Затем я устанавливаю сокет в классе Runnable и вызываю notify () для переданного объекта после подключения клиента к порту.Это должно позволить серверу перезапустить свой цикл, создав другой экземпляр класса Runnable после получения уведомления.Однако в настоящее время wait () не достигается до тех пор, пока клиент не будет закрыт.Вот три соответствующих класса, которые у меня есть:
Класс сервера:
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.HashMap;
public class Server {
public static void main(String[] args){
HashMap<String, PortDummy> portDummies = new HashMap<String, PortDummy>();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8000);
} catch (IOException e1) {
e1.printStackTrace();
}
for(;;){
Object block = new Object();
PortDummy dummy = new PortDummy(serverSocket, block, portDummies);
System.out.println("Running dummy port...");
dummy.start();
try {
synchronized(block){
System.out.println("Waiting...");
block.wait();
System.out.println("Block notified.");
}
} catch (InterruptedException e) {
System.out.println("Can't be interrupted!");
e.printStackTrace();
}
}
}
}
Класс PortDummy (Runnable):
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class PortDummy extends Thread {
private Object block;
private HashMap<String, PortDummy> portDummies;
private String clientName = null;
ServerSocket serverSocket;
BufferedReader socketIn;
PrintWriter socketOut;
public PortDummy(ServerSocket serverSocket, Object block, HashMap<String, PortDummy> portDummies){
this.block = block;
this.portDummies = portDummies;
this.serverSocket = serverSocket;
}
@Override
public void run() {
try {
System.out.println("Starting dummy port...");
Socket clientSocket = serverSocket.accept();
System.out.println("Connection made.");
synchronized(block){
System.out.print("Notifying...");
block.notify();
System.out.println("...done.");
}
socketIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
socketOut = new PrintWriter(clientSocket.getOutputStream(), true);
String inContent;
boolean loggedIn = false;
while((inContent = socketIn.readLine()) != null){
socketOut.println("Server Echo: " + inContent);
if(inContent.startsWith("/exit")){
if(loggedIn){
portDummies.remove(clientName);
System.out.println(clientName + " signed out. Removed from portDummies.");
}
else{
System.out.println("Closing...");
}
}
else if(inContent.startsWith("/register")){
System.out.println("/register accepted");
if(!loggedIn){
if(registerUser(inContent)){
System.out.println("Successfully registered.");
socketOut.println(clientName + " successfully registered.");
loggedIn = true;
}else{
socketOut.print("That user already exists.");
}
}
else{
socketOut.print("Already logged in.");
}
}
else if(inContent.startsWith("/tell")){
if(!loggedIn){
socketOut.println("You need to log in.");
}
else{
String[] parts = inContent.split("\\w");
String[] withoutCommand = new String[parts.length-1];
for(int i = 1; i<parts.length-1; i++){
withoutCommand[i] = parts[i];
}
String[] messageParts = new String[withoutCommand.length-1];
String message = "";
for(int j = 1; j<withoutCommand.length-1; j++){
message += withoutCommand[j] + " ";
}
String recipient = withoutCommand[0];
sendMessage(recipient, message);
}
}
else if(inContent.startsWith("/help")){
socketOut.print("/help ~~~~~~~ List all commands. \n " +
"/register <username> ~~~~~~~ Register a new user with 'username'. \n " +
"/tell <username> <message> ~~~~~~~ Send 'username' text 'message'. \n " +
"/exit ~~~~~~~ Log out.");
}
}
System.out.println("Shutting down client connections...");
socketOut.close();
socketIn.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
System.out.println("IOException!");
e.printStackTrace();
}
}
private boolean registerUser(String text){
System.out.println("Registering user...");
String user = text.substring(10);
if((user != null) && !(portDummies.containsKey(user))){
portDummies.put(user, this);
clientName = user;
System.out.println(user + " registered.");
return true;
}
return false;
}
private void sendMessage(String username, String message){
if(portDummies.containsKey(username)){
PortDummy recip = portDummies.get(username);
recip.getSocketOutput().println(clientName + ": " + message);
}
else{
socketOut.write("User " + username + " doesn't exist.");
}
}
public PrintWriter getSocketOutput(){
return socketOut;
}
}
Класс клиента:
package client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import java.io.IOException;
public class Client {
protected String username;
public static void main(String[] args){
try{
Socket serverSocket = new Socket("localhost", 8000);
BufferedReader socketIn = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
PrintWriter socketOut = new PrintWriter(serverSocket.getOutputStream(), true);
Scanner keyboardInputScanner = new Scanner(System.in);
String keyboardInput, serverInput;
System.out.println("Welcome to Chris Volkernick's Server IM Client! \n" +
"Type '/register <username>' to register, '/list' to list connected users," +
"\n or '/tell <username> <message>' to send a user a message. '/help' lists these commands. (Type '/exit' to sign out.)");
while((keyboardInput = keyboardInputScanner.nextLine()) != null){
System.out.println("Input '" + keyboardInput + "' read on client side.");
if(keyboardInput.equals("/exit")){
socketOut.println("/exit");
socketOut.close();
socketIn.close();
serverSocket.close();
}else{
socketOut.println(keyboardInput);
while((serverInput = socketIn.readLine()) != null){
System.out.println(serverInput);
}
}
}
keyboardInputScanner.close();
}catch(IOException e){
System.out.println("IOException!");
e.printStackTrace();
}
}
}
Я что-то не так делаю с wait () и / или notify ()?
EDIT: я также пытался изменить навесное оборудование Runnable для расширения Thread, затем изменив .run () на сервере на.start (), но это дает мне эту ошибку:
java.net.BindException: Address already in use: JVM_Bind
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:365)
at java.net.ServerSocket.bind(ServerSocket.java:319)
at java.net.ServerSocket.<init>(ServerSocket.java:185)
at java.net.ServerSocket.<init>(ServerSocket.java:97)
at server.PortDummy.run(PortDummy.java:28)
РЕДАКТИРОВАТЬ 2: Кажется, что он работает так, как сейчас, с точки зрения запуска новых потоков.Однако теперь я сталкиваюсь с другой проблемой: после ввода команды на стороне клиента любого данного клиента я не могу вводить дополнительные команды.Первая команда будет работать нормально (минус / выход; пока не совсем понял, как это должно работать), просто ничего не могу сделать после этого.Например, я могу зарегистрироваться (войти), но после этого больше ничего.Я могу зайти в другой экземпляр Client и перечислить всех текущих пользователей (работает), но опять же, после этого я не могу вводить дополнительные команды.Есть идеи, что может быть причиной этого?