当我同Scanner进行客户端与服务端之间的信息发送与读取时,发生了一些问题:
服务端:
//对信息读取并输入
if (in.hasNext()) {
updateFunction.accept(new Streams(in, out), this.name);
}
客户端:
while (true){
if(scanner.hasNext())
System.out.print(scanner.nextLine());
}
Scanner类无缘无故堵塞,我不知道该如何处理这个问题。
以下是我的源代码:
服务端:
package www.studynet.com;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.function.BiConsumer;
public class ServerMain {
public class SocketListener{
public static class Streams{
Scanner in;
PrintWriter out;
Streams(Scanner in, PrintWriter out){
this.in = in;
this.out = out;
}
Streams(){
this(null,null);
}
}
public volatile Socket socket;
public Thread thread;
public String name;
//信息输入时要做的函数
public BiConsumer<Streams,String> updateFunction;
SocketListener(){
this(null,null,null);
}
SocketListener(Socket socket, String name,
BiConsumer<Streams,String> doWhenUpdate){
this.socket = socket;
this.name = name;
this.updateFunction = doWhenUpdate;
thread = new Thread(()->{
try(Scanner in = new Scanner(this.socket.getInputStream(),StandardCharsets.UTF_8);
PrintWriter out = new PrintWriter(this.socket.getOutputStream())
) {
while (true) {
//对信息读取并输入(问题代码)
if (in.hasNext()) {
updateFunction.accept(new Streams(in, out), this.name);
}
//检测对方是否断开连接
try {
this.socket.sendUrgentData(0xFF);
} catch (Exception e) {
connectSockets.remove(this);
System.out.println("Closed, name=" + this.name + ", address=" +
this.socket.getInetAddress().getHostAddress());
break;
}
}
} catch (IOException e) {
System.err.println(this.name + "get stream error.");
e.printStackTrace();
}
});
thread.start();
}
}
public static final int PORT = 2556;
public ServerSocket serverSocket;
public LinkedList<SocketListener> connectSockets;
public volatile boolean serverStop = false;
public Thread getConnectedSocketThread;
private int connectSocketCount = 0;
public ServerMain() throws IOException {
serverSocket = new ServerSocket(PORT);
connectSockets = new LinkedList<>();
System.out.println("Created server, port=" + PORT + ", address=" +
serverSocket.getInetAddress().getHostAddress() + ":" + PORT);
//获得链接的套接字
getConnectedSocketThread = new Thread(()->{
Thread thread = new Thread();
while (true){
//当exit命令执行时,代表服务器关闭,则关闭等待线程
if(serverStop){
if(!thread.isAlive()){
thread.interrupt();
}
break;
}
//实现服务器连接
if(!thread.isAlive()){
thread = new Thread(()->{
try {
Socket connected = serverSocket.accept();
System.out.println("Connected=" +
connected.getInetAddress().getHostAddress() +
",name=" + ++connectSocketCount);
synchronized (connectSockets){
connectSockets.add(new SocketListener(connected,
String.valueOf(connectSocketCount),
(streams,name)->{
String info = "";
while (streams.in.hasNextLine()){
info += streams.in.nextLine();
}
System.out.println("name:" + name + ",info=" + info);
}
));
}
} catch (IOException e) {
if(!serverStop) {
System.err.print("Connected error.");
e.printStackTrace();
}
}
});
thread.start();
}
}
//服务器关闭之后,关闭所有连接
for(var socket : connectSockets){
try {
socket.socket.close();
} catch (IOException e) {
System.err.println("Close error.");
e.printStackTrace();
}
}
try {
serverSocket.close();
} catch (IOException e) {
System.err.println("Close server error.");
e.printStackTrace();
}
System.out.println("Close the server");
});
getConnectedSocketThread.start();
}
public void stop() {
this.serverStop = true;
}
public static void main(String[] args) {
try {
ServerMain serverMain = new ServerMain();
Scanner inputScanner = new Scanner(System.in, StandardCharsets.UTF_8);
whileLoop:
while(true){
//命令处理
if(inputScanner.hasNextLine()){
var value = inputScanner.nextLine();
//退出命令
if(value.equals("exit")){
serverMain.stop();
break whileLoop;
}
//列表命令
else if(value.equals("list")){
System.out.println("LIST---");
for(var socket : serverMain.connectSockets){
System.out.println("name=" + socket.name + ", address=" +
socket.socket.getInetAddress().getHostAddress());
}
System.out.println("---END_LIST");
System.out.println();
System.out.println();
}
//信息发送命令
else if(value.equals("send")){
System.out.print("Input name:");
String name = inputScanner.nextLine();
System.out.print("Input info:");
String info = inputScanner.nextLine();
try {
Socket socket = null;
for (var socketListener : serverMain.connectSockets){
if(socketListener.name.equals(name)){
socket = socketListener.socket;
}
}
if(socket == null){
throw new Exception("Cannot find socket by name:" + name);
}
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.print(info);
printWriter.flush();
System.out.println("Send successfully.");
}catch (Exception exception){
System.out.println("Send failed, caused by:");
exception.printStackTrace();
}
}
}
}
inputScanner.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端:
package www.studynet.com;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class ConnectServer {
public static void main(String[] args){
try(Socket socket = new Socket("localhost",ServerMain.PORT)){
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println("2312");
printWriter.flush();
Scanner scanner = new Scanner(socket.getInputStream(),StandardCharsets.UTF_8);
while (true){
if(scanner.hasNext())
System.out.print(scanner.nextLine());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
通过断点调试发现,问题好像处在scanner.nextLine和scanner.next上。
并且,我发现当Socket关闭时,线程才停止堵塞。
不用加scanner.hasNext()