所以我正在实现一个简单的Java Socket Chat程序,但我遇到的问题是在下面的代码中。目前我的客户代码为will first read from socket then output to the screen
,then read from console then output to socket input
。但是这种方式我无法在从控制台读取时从套接字打印消息,直到用户点击enter
什么是解决这个问题的最佳方法,是多线程(如果可以,我可以得到一个例子吗?),还是有其他传统方式来解决这个问题。
while(true){
//read from socket, -> output to screen
String line = sockin.readLine();
System.out.println(line);
//read console, -> write to socket
String consolein = consoleReader.readLine();
sockout.println(consolein);
}
答案 0 :(得分:1)
是的,您应该使用多线程。您需要生成两个线程,一个用于读取用户的输入,另一个用于从服务器/另一个客户端读取输出。但是,在基于控制台的聊天应用程序中使用多线程时,一个问题是:将输出与服务器和用户输入分开。
示例多线程客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ThreadedClient {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println(
"Usage: java ThreadedClient <host name> <port number>");
System.exit(1);
}
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);
try {
Socket serverSocket = new Socket(hostName, portNumber);
ClientServerOutputReader csor = new ClientServerOutputReader(serverSocket);
csor.start();
ClientUserInputReader cuir = new ClientUserInputReader(serverSocket);
cuir.start();
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
class ClientServerOutputReader extends Thread {
Socket serverSocket;
public ClientServerOutputReader(Socket serverSocket){
this.serverSocket = serverSocket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(
new InputStreamReader(serverSocket.getInputStream()));
String outputFromServer="";
while((outputFromServer=in.readLine())!= null){
//This part is printing the output to console
//Instead it should be appending the output to some file
//or some swing element. Because this output may overlap
//the user input from console
System.out.println(outputFromServer);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientUserInputReader extends Thread {
Socket serverSocket;
public ClientUserInputReader(Socket serverSocket){
this.serverSocket = serverSocket;
}
public void run(){
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
PrintWriter out;
try {
out = new PrintWriter(serverSocket.getOutputStream(), true);
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行:java ThreadedClient localhost 1982
示例回显服务器
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java EchoServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
try (
ServerSocket serverSocket =
new ServerSocket(Integer.parseInt(args[0]));
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println("From Server:"+inputLine);
Thread.sleep(2000);
out.println("Server status on");
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
在上面的服务器程序中,当客户端发生用户输入时,会添加手动睡眠和自定义消息以模拟服务器的输出。
运行:java EchoServer 1982