我在服务器(我自己)和客户端(不同网络中的朋友)之间进行了一对一的套接字聊天工作。现在我尝试做同样的事情,但我尝试创建多个连接,将它们放在Executors.newFixedThreadPool(poolSize)
中,其中部分代码来自ExecutorService
文档。
服务器工作,并接受连接,但是,当我尝试建立第二个连接并向其发送消息时,会出现问题。虽然每个客户端都可以向服务器发送消息,但服务器只能向第一个客户端发送消息。
以下是完整代码:
public class MultipleServer implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
Scanner console;
public MultipleServer(int port, int poolSize, Scanner mainconsole)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
console = mainconsole;
}
public void run() {
try {
for(;;) {
pool.execute(new Handler(serverSocket.accept(), console));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
private Socket socket;
private Scanner console;
private String name = "undefined";
Handler(Socket socket, Scanner console)
{
this.socket = socket;
this.console = console;
}
public void run()
{
if (socket.isConnected())
{
System.out.println("connection from " + socket.getLocalAddress().getHostAddress());
Thread inputthread = new Thread(new Runnable()
{
@Override
public void run()
{
PrintWriter out;
try
{
out = new PrintWriter(socket.getOutputStream(), true);
out.println("Welcome to my server. Input your name");
out.flush();
String line;
while ((line = console.nextLine()) != null)
{
if (line.contains("/"))
{
if (line.equals("/q " + name))
{
out.println("Connection closing");
System.out.println("Connection to " + name + "closing");
out.close();
socket.close();
} else if (line.substring(0, name.length() + 3).equals("/m " + name))
{
out.println(line.substring(name.length() + 4));
out.flush();
}
} else
{
System.out.println("Incorrect command");
}
}
if (socket.isClosed())
{
out.close();
}
} catch (IOException e)
{
e.printStackTrace();
}
}
});
Thread outputthread = new Thread(new Runnable()
{
int msgno = 0;
@Override
public void run()
{
BufferedReader in;
try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (!socket.isClosed())
{
while (!in.ready())
{
Thread.sleep(100);
}
String msg = in.readLine();
if (msgno == 0)
{
name = msg;
msgno++;
} else
{
System.out.println(name + ": " + msg);
}
synchronized (this)
{
this.wait(100);
}
}
if (socket.isClosed())
{
in.close();
}
} catch (IOException e)
{
e.printStackTrace();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
inputthread.start();
outputthread.start();
}
}
public static void main(String[] args) throws IOException
{
int connections = 10;
int port = 80;
Scanner scanner = new Scanner(System.in);
MultipleServer server = new MultipleServer(port, connections, scanner);
server.run();
}
}
更具体地说,引发了异常:
Exception in thread "Thread-2" java.lang.IndexOutOfBoundsException: end
at java.util.regex.Matcher.region(Unknown Source)
at java.util.Scanner.findPatternInBuffer(Unknown Source)
at java.util.Scanner.findWithinHorizon(Unknown Source)
at java.util.Scanner.nextLine(Unknown Source)
at Handler$1.run(MultipleServer.java:61)
at java.lang.Thread.run(Unknown Source)
有问题的行是:
while((line=console.nextLine())!=null){
澄清:当第二个用户加入服务器时会发生此异常。当我键入/ m user1消息时,第一个用户获取预期的消息,当我输入/ m user2消息时,没有错误,但user2没有收到消息。此外,没有"不正确的命令"服务器控制台上的消息,表示第二个用户的输出不起作用
答案 0 :(得分:1)
主要问题 - 你有太复杂的线程管理:几个线程试图同时从控制台输入读取:用户1读者线程和用户2读取线程。
您应该引入一个路由器线程,负责与管理员进行通信,并通过共享的并发结构管理生成的线程之间的所有消息。
对于此类任务,最好使用任何现有的框架,例如netty或nirvana messaging。