我是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类,我创建了新的runnable类并将该变量传递给线程类。灵感来自这个问题:"implements Runnable" vs. "extends Thread"。
答案 0 :(得分:1)
我认为问题在于服务器和客户端都在等待任何输入。服务器:
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 = new PrintWriter(socket.getOutputStream(), true);
请参阅PrintWriter's JavaDoc:True表示换行时自动刷新。
我测试了这个设置,它对我有用。我能够从客户端向服务器发送一些东西。
然而,这只是第一步。对于客户端和服务器,我都会将读取和写入实现为单独的线程。并且没有优雅关闭已实现的套接字。可以在Oracle上找到更完整而简单的示例。