客户端未向服务器发送消息 Java 套接字
Client side is not sending message to server Java Socket
我正在学习 java 中的套接字,但是当我是 运行 一个从客户端向服务器端发送消息的程序时,它没有显示消息。如果我在客户端输入一些文本,它不会显示在服务器端,但如果我输入 endProcess,它就会停止 运行。这意味着消息正在通过,只是没有显示。
我的 Client.java 代码在这里:
import java.net.*;
import java.io.*;
public class Client{
Socket soc;
DataInputStream dis;
DataOutputStream dos;
public Client(){
try{
soc = new Socket("(Address)",5000);
System.out.println("Connection Established");
dis = new DataInputStream(System.in);
dos = new DataOutputStream(soc.getOutputStream());
System.out.println("Streams connected");
}catch(UnknownHostException u){
System.out.println(u);
}catch(IOException i){
System.out.println(i);
}
String line = "";
while(!line.equals("endConnection")){
try{
line = dis.readUTF();
dos.writeUTF(line);
}catch(IOException i){
System.out.println(i);
}
}
try {
soc.close();
dis.close();
dos.close();
} catch (Exception e) {
System.out.println(e)
}
}
public static void main(String[] args) {
new Client();
}
}
这是我的 Server.java 代码:
import java.net.*;
import java.io.*;
public class Server {
ServerSocket serSoc;
Socket soc;
DataInputStream dis;
public Server(){
try {
serSoc = new ServerSocket(5000);
System.out.println("Server Online");
soc = serSoc.accept();
System.out.println("Client Connected");
dis = new DataInputStream(new BufferedInputStream(soc.getInputStream()));
String line = "";
System.out.println("Waiting for input...");
while(!line.equals("endConnection")){
line = dis.readUTF();
System.out.println(line);
}
System.out.println("Client disconnected");
soc.close();
dis.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
new Server();
}
}
这里有很多问题。
双工协议问题
line = dis.readUTF();
dos.writeUTF(line);
这行不通; dis.readUTF()
行将阻塞(冻结),直到读取一行。问题是,有时你没有什么可发送的而你想阅读,而你没有什么可读的东西又想发送。实际上,您需要完全重新设计它;你需要 2 个线程。此时您会遇到多核问题,需要同步原语 and/or java.util.concurrent
类 用于在 2 个线程之间共享的所有数据。
或者,采用严格推或拉的模型(在任何给定时间,双方都已经知道谁可以发送,而如果另一方想发送,他们根本做不到。例如,每一方发送一个简单的'NOTHING TO DO'每秒发送消息,每次交换位置。当然,这是一个非常低效的算法。但可以在不涉及多线程的情况下编写。
刷新和关闭问题
dos.writeUTF(line);
这实际上不会发送任何内容,或者至少不保证会发送任何内容。要在 Internet 上发送任何数据,它会被包裹在一个具有大量开销的数据包中。所以,事情会被缓冲,直到有一个完整的数据包要发送。这意味着该行不执行任何操作。它只是填充一个缓冲区,没有数据包出去。您首先需要关闭或冲洗。 dos.flush()
也许会有帮助。这是个大问题,因为以后你会:
soc.close();
dis.close();
dos.close();
您首先关闭套接字,然后,关闭套接字。然后关闭流,这也将发送仍然停留在缓冲区中的任何内容,除非发送失败,因为套接字已经关闭。换句话说,您 .writeUTF()
-ed 的行?它永远不会到达那里。您首先将其放入缓冲区,然后关闭套接字,然后发送缓冲区,因为套接字已经关闭,缓冲区将无法工作。
错误处理
} catch (Exception e) {
System.out.println(e);
}
太可怕了。不要这样做。您的代码通过打印一些东西来对任何问题做出反应 并继续前进 。这意味着如果出现任何问题,客户端将开始发送无休止的异常跟踪队列并在运气好时锁定系统。您希望代码在出现问题时停止 运行。到目前为止,最简单的方法是将 throws IOException
粘贴在您的构造函数和 main 方法上,这是允许的。遥远的第二个最佳选择是将您的 'eh whatever' catch 块配置为 throw new RuntimeException("unhandled", e);
而不是 e.printStackTrace()
.
你所做的 (System.out.println(e);
) 更糟糕 - 你正在丢弃非常有用的信息,例如堆栈跟踪和因果链。
我正在学习 java 中的套接字,但是当我是 运行 一个从客户端向服务器端发送消息的程序时,它没有显示消息。如果我在客户端输入一些文本,它不会显示在服务器端,但如果我输入 endProcess,它就会停止 运行。这意味着消息正在通过,只是没有显示。
我的 Client.java 代码在这里:
import java.net.*;
import java.io.*;
public class Client{
Socket soc;
DataInputStream dis;
DataOutputStream dos;
public Client(){
try{
soc = new Socket("(Address)",5000);
System.out.println("Connection Established");
dis = new DataInputStream(System.in);
dos = new DataOutputStream(soc.getOutputStream());
System.out.println("Streams connected");
}catch(UnknownHostException u){
System.out.println(u);
}catch(IOException i){
System.out.println(i);
}
String line = "";
while(!line.equals("endConnection")){
try{
line = dis.readUTF();
dos.writeUTF(line);
}catch(IOException i){
System.out.println(i);
}
}
try {
soc.close();
dis.close();
dos.close();
} catch (Exception e) {
System.out.println(e)
}
}
public static void main(String[] args) {
new Client();
}
}
这是我的 Server.java 代码:
import java.net.*;
import java.io.*;
public class Server {
ServerSocket serSoc;
Socket soc;
DataInputStream dis;
public Server(){
try {
serSoc = new ServerSocket(5000);
System.out.println("Server Online");
soc = serSoc.accept();
System.out.println("Client Connected");
dis = new DataInputStream(new BufferedInputStream(soc.getInputStream()));
String line = "";
System.out.println("Waiting for input...");
while(!line.equals("endConnection")){
line = dis.readUTF();
System.out.println(line);
}
System.out.println("Client disconnected");
soc.close();
dis.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
new Server();
}
}
这里有很多问题。
双工协议问题
line = dis.readUTF(); dos.writeUTF(line);
这行不通; dis.readUTF()
行将阻塞(冻结),直到读取一行。问题是,有时你没有什么可发送的而你想阅读,而你没有什么可读的东西又想发送。实际上,您需要完全重新设计它;你需要 2 个线程。此时您会遇到多核问题,需要同步原语 and/or java.util.concurrent
类 用于在 2 个线程之间共享的所有数据。
或者,采用严格推或拉的模型(在任何给定时间,双方都已经知道谁可以发送,而如果另一方想发送,他们根本做不到。例如,每一方发送一个简单的'NOTHING TO DO'每秒发送消息,每次交换位置。当然,这是一个非常低效的算法。但可以在不涉及多线程的情况下编写。
刷新和关闭问题
dos.writeUTF(line);
这实际上不会发送任何内容,或者至少不保证会发送任何内容。要在 Internet 上发送任何数据,它会被包裹在一个具有大量开销的数据包中。所以,事情会被缓冲,直到有一个完整的数据包要发送。这意味着该行不执行任何操作。它只是填充一个缓冲区,没有数据包出去。您首先需要关闭或冲洗。 dos.flush()
也许会有帮助。这是个大问题,因为以后你会:
soc.close(); dis.close(); dos.close();
您首先关闭套接字,然后,关闭套接字。然后关闭流,这也将发送仍然停留在缓冲区中的任何内容,除非发送失败,因为套接字已经关闭。换句话说,您 .writeUTF()
-ed 的行?它永远不会到达那里。您首先将其放入缓冲区,然后关闭套接字,然后发送缓冲区,因为套接字已经关闭,缓冲区将无法工作。
错误处理
} catch (Exception e) { System.out.println(e); }
太可怕了。不要这样做。您的代码通过打印一些东西来对任何问题做出反应 并继续前进 。这意味着如果出现任何问题,客户端将开始发送无休止的异常跟踪队列并在运气好时锁定系统。您希望代码在出现问题时停止 运行。到目前为止,最简单的方法是将 throws IOException
粘贴在您的构造函数和 main 方法上,这是允许的。遥远的第二个最佳选择是将您的 'eh whatever' catch 块配置为 throw new RuntimeException("unhandled", e);
而不是 e.printStackTrace()
.
你所做的 (System.out.println(e);
) 更糟糕 - 你正在丢弃非常有用的信息,例如堆栈跟踪和因果链。