我是 Java 新手,我正在尝试学习线程和套接字。因此决定按照官方 java 教程制作简单的客户端-服务器应用程序。我的想法很简单 - 服务器等待连接,如果出现,它会使用新的套接字、输入和输出创建新线程。客户端->建立连接;带有套接字、输入、输出和 stdIn 的新线程(读取行,然后将其发送到服务器)。但我的代码出了点问题(不知道为什么)。连接已建立,没有异常。有人可以解释为什么不起作用以及如何修复它吗?另外,您对代码有什么建议吗(可能不是最佳实践之类的):
Client side:
public class Client {
private BufferedReader reader;
private Socket sock;
private PrintWriter writer;
public static void main(String[] args) {
Client client = new Client();
client.go();
}
public void go() {
setUpNetworking();
}
private void setUpNetworking() {
try{
sock = new Socket("127.0.0.1", 5000);
System.out.println("Network established");
ServerThread serverThread= new ServerThread(sock);
serverThread.start();
System.out.println("Type your message: ");
} catch (IOException e) {
System.out.println("Problem with establishing the network: " + e);
}
}
class ServerThread extends Thread {
Socket socket;
PrintWriter out;
BufferedReader in;
BufferedReader stdIn;
ServerThread(Socket socket) {
this.socket = socket;
try{
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
}catch (IOException e) {
System.out.println("Problem with trying to read/write to server: " + e);
}
}
@Override
public void run() {
String fromServer;
String fromClient;
while(true){
try{
if((fromServer = in.readLine()) != null) System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null) out.println(fromClient);
}catch(Exception e) {
System.out.println("msg exception: " + e);
}
}
}
}
}
服务器端:
public class Server {
//Run server until keepGoing = false
private boolean keepGoing = true;
public static void main(String[] args) {
Server server = new Server();
server.go();
}
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000);
while(keepGoing) {
Socket clientSocket = serverSocket.accept();
ClientThread t = new ClientThread(clientSocket);
t.start();
}
} catch (IOException e) {
System.out.println("Problem with socket/network: " + e);
}
}
class ClientThread extends Thread {
Socket clientSocket;
PrintWriter out;
BufferedReader in;
ClientThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try{
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
System.out.println("Problem with creating in/out: " + e);
}
}
@Override
public void run() {
String message;
while(keepGoing) {
try{
message = in.readLine();
out.println(message);
System.out.println(message);
} catch (IOException e){
System.out.println("Exception while try to read line: " + e);
}
}
}
}
}
PS 我对代码做了一些更改 - 我没有创建 ClientThread 类,而是创建了新的可运行类并将该变量传递给线程类。受到这个问题的启发:"implements Runnable" vs. "extends Thread" 。
最佳答案
我认为问题在于服务器和客户端都在等待任何输入。服务器:
message = in.readLine();
客户:
if((fromServer = in.readLine()) != null)
System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null)
out.println(fromClient);
但是客户端代码已经阻塞在 fromServer = in.readLine()
部分,因此它永远无法从标准输入读取数据,因此不会向服务器发送任何内容。
您可以将尝试从标准读取转移到 setUpNetworking
方法中,紧接在 System.out.println("Type your message: ");
之后。构建一个循环,如果用户键入“exit”或“quit”或类似的内容,则退出该循环:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String read = "";
do {
read = stdIn.readLine();
System.out.println("Read from stdin: " + read);
serverThread.send(read);
}
while (!read.equals("exit"));
ServerThread.send()
方法很简单:
void send(String string) {
System.out.println("Sending to server: " + string);
out.println(string);
}
但是,要使其正常工作,您必须在写入 out 后手动刷新流,或者使用以下构造函数:
out = new PrintWriter(socket.getOutputStream(), true);
请参阅PrintWriter's JavaDoc : True 表示在换行符上自动刷新。
我测试了这个设置,它对我有用。我能够从客户端向服务器发送一些内容。
然而,这只是第一步。我会将客户端和服务器的读取和写入实现为单独的线程。并且还没有实现套接字的正常关闭。更完整但简单的示例可以在 Oracle 上找到。 .
关于java - 在 Java 中的简单客户端-服务器应用程序中读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32299153/