英文:
BufferReader not receiving data from socket apparently. Simple chat service
问题
请您友好地查看我的代码,并告诉我可能出现的问题是什么?
我正在学习Java网络编程和网络通信,纯粹是为了好玩,我尝试遵循这个链接https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html 中的内容,但我并没有创建协议,而是尝试在服务器和客户端之间创建简单的消息交换。
标准输出没有显示任何内容,当我进行调试时,BufferReader缓冲区为空,似乎没有接收到数据。我还没有使用Wireshark进行检查,但我怀疑问题可能更加琐碎,是由于我经验不足造成的结果。
以下是客户端代码(它首先向服务器发送简单的消息“Hello There”):
try (BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter toServer = new PrintWriter(socket.getOutputStream());
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
) {
toServer.println("Hello there!");
while (!goodbye) {
if (fromServer.ready()) //如果流为空,这会防止冻结
msgFromServer = fromServer.readLine();
if (msgFromServer != null) {
System.out.println("Server: " + msgFromServer);
if (msgFromServer.equals("Bye"))
goodbye = true;
}
msgToServer = consoleInput.readLine();
if (msgToServer != null) {
toServer.println(msgToServer);
if (msgToServer.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
现在是服务器端:
try (Socket clientSocket = socket.accept();
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream());
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
) {
while (!goodbye) {
if (fromClient.ready())
msgFromClient = fromClient.readLine();
if (msgFromClient != null) {
System.out.println("Client: " + msgFromClient);
if (msgFromClient.equals("Bye"))
goodbye = true;
}
msgToClient = consoleInput.readLine();
if (msgToClient != null) {
toClient.println(msgToClient);
if (msgToClient.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch (IOException ex) {
System.out.println(ex);
}
我已经有点困惑,因为有太多的循环,我想知道它们是否可能出现问题,我的策略是否总体上是错误的?也许我应该设置一些标志,比如“等待服务器回复”。我真的很困惑。
编辑:在每个类中注释掉 if (BufferedReader.ready())
方法之后,它就工作了。不过我仍然不确定为什么会这样,所以我不会立刻关闭它,但在找到答案后,我会在另一个回答中进行解释。
到目前为止,我的“修复”代码看起来像这样:
try (Socket clientSocket = socket.accept();
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
) {
while (!goodbye) {
// if (fromClient.ready())
msgFromClient = fromClient.readLine();
if (msgFromClient != null) {
System.out.println("Client: " + msgFromClient);
if (msgFromClient.equals("Bye"))
goodbye = true;
}
msgToClient = consoleInput.readLine();
if (msgToClient != null) {
toClient.write(msgToClient);
toClient.newLine();
toClient.flush();
if (msgToClient.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch (IOException ex) {
System.out.println(ex);
}
我忘记了,但我还添加了 Socket.TcpSetNoDelay(true)
到客户端套接字中。
英文:
Could You kindly take a glance at my code and tell me what could be the problem here?
I am learning java network programming and networking in general for fun and i try to follow this https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html but instead of creating protocol i try to just create simple exchange of messages between server and client.
Nothing shows up in standard output and when i am debugging it BufferReader buffer is empty and seems to not receive data. I have yet to check it with Wireshark but i suspect cause is much more trivial and a result of my inexperience.
Here is the client code (It messages server first with a simple "Hello There")
try(BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter toServer = new PrintWriter(socket.getOutputStream());
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
toServer.println("Hello there!");
while(!goodbye){
if(fromServer.ready()) //if stream is empty this prevents a freeze
msgFromServer = fromServer.readLine();
if(msgFromServer != null) {
System.out.println("Server: " + msgFromServer);
if(msgFromServer.equals("Bye"))
goodbye = true;
}
msgToServer = consoleInput.readLine();
if(msgToServer != null) {
toServer.println(msgToServer);
if(msgToServer.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
And now server side:
try(Socket clientSocket = socket.accept();
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream());
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
while(!goodbye){
if(fromClient.ready())
msgFromClient = fromClient.readLine();
if(msgFromClient != null) {
System.out.println("Client: " + msgFromClient);
if(msgFromClient.equals("Bye"))
goodbye = true;
}
msgToClient = consoleInput.readLine();
if(msgToClient != null) {
toClient.println(msgToClient);
if(msgToClient.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch(IOException ex){
System.out.println(ex);
}
I am a bit confused already by all the loops and wonder if it is possible they are out of sync somehow and my strategy is generally wrong ? perhaps should i set some flags as "waiting_for_server_reply" I am really confused
Edit: After commenting out if(BufferedReader.ready())
methods in each class it worked. I am still unsure why though so i won't close it just yet but after i find answer i will explain in separate answer
So far my 'fixed' code looks like:
try(Socket clientSocket = socket.accept();
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
while(!goodbye){
//if(fromClient.ready())
msgFromClient = fromClient.readLine();
if(msgFromClient != null) {
System.out.println("Client: " + msgFromClient);
if(msgFromClient.equals("Bye"))
goodbye = true;
}
msgToClient = consoleInput.readLine();
if(msgToClient != null) {
toClient.write(msgToClient);
toClient.newLine();
toClient.flush();
if(msgToClient.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch(IOException ex){
System.out.println(ex);
}
I forgot but i also added Socket.TcpSetNoDelay(true)
to client Socket
答案1
得分: 0
我认为你应该尝试使用熟悉的类来进行读写操作。例如,如果你正在使用 BufferedReader
进行读取,那么写入时应该使用 BufferedWriter
。
英文:
I think you should try to use familiar classes for reading and writing. For example if you are using BufferedReader
for reading then you should use BufferedWriter
for writing.
答案2
得分: 0
在每个类中注释掉 if(BufferedReader.ready())
方法后,它就正常工作了。看起来我对这个方法的作用有误解。我添加了 .ready()
方法,因为服务器在从客户端的流中读取数据后没有使用 flush()
方法,导致在调试过程中出现了服务器在 .readLine()
处冻结的情况,并且指示可能会有问题。
正如 @VGR 指出的那样,ready()
方法只是用来判断是否存在等待流数据到达的延迟。第一条消息必须有延迟,所以直到下一个缓冲区读取时才显示,当缓冲区中已经有内容时。
我还在客户端的 Socket 中添加了 Socket.TcpSetNoDelay(true)
。
现在代码看起来是这样的:
服务器:
try(Socket clientSocket = socket.accept();
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
while(!goodbye){
//if(fromClient.ready())
msgFromClient = fromClient.readLine();
if(msgFromClient != null) {
System.out.println("Client: " + msgFromClient);
if(msgFromClient.equals("Bye"))
goodbye = true;
}
msgToClient = consoleInput.readLine();
if(msgToClient != null) {
toClient.write(msgToClient);
toClient.newLine();
toClient.flush();
if(msgToClient.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch(IOException ex){
System.out.println(ex);
}
客户端:
Clientv2(){
socket = new Socket();
try {
socket.setTcpNoDelay(true); //this is new too
} catch (SocketException e) {
e.printStackTrace();
}
}
public void connect() {
try {
socket.connect(new InetSocketAddress(serverHostname, serverPort));
}
catch (IOException ex){
System.out.println(ex);
}
try(BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter toServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
toServer.write("Hello there!");
toServer.newLine();
toServer.flush();
while(!goodbye){
//if(fromServer.ready()) //culprit
msgFromServer = fromServer.readLine();
if(msgFromServer != null) {
System.out.println("Server: " + msgFromServer);
if(msgFromServer.equals("Bye"))
goodbye = true;
}
msgToServer = consoleInput.readLine();
if(msgToServer != null) {
toServer.write(msgToServer);
toServer.newLine();
toServer.flush();
if(msgToServer.equals("Bye"))
goodbye = true;
}
}
socket.close();
}
英文:
After commenting out if(BufferedReader.ready())
methods in each class it worked.
It looks like i had wrong idea what this method is doing.
I added the .ready() method because server froze on .readLine() because i didn't use flush() method after writing to the stream from the client and during debugging it indicated that there may be a problem here.
As @VGR pointed out
All the ready()
method does is telling whether there was a delay waiting for stream data to arrive or not. First message had to have a delay so it didn't show until the next buffer read when it was already something in the buffer.
I also added Socket.TcpSetNoDelay(true)
to client Socket
Code now looks like this
Server:
try(Socket clientSocket = socket.accept();
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
while(!goodbye){
//if(fromClient.ready())
msgFromClient = fromClient.readLine();
if(msgFromClient != null) {
System.out.println("Client: " + msgFromClient);
if(msgFromClient.equals("Bye"))
goodbye = true;
}
msgToClient = consoleInput.readLine();
if(msgToClient != null) {
toClient.write(msgToClient);
toClient.newLine();
toClient.flush();
if(msgToClient.equals("Bye"))
goodbye = true;
}
}
socket.close();
} catch(IOException ex){
System.out.println(ex);
}
Client
Clientv2(){
socket = new Socket();
try {
socket.setTcpNoDelay(true); //this is new too
} catch (SocketException e) {
e.printStackTrace();
}
}
public void connect() {
try {
socket.connect(new InetSocketAddress(serverHostname, serverPort));
}
catch (IOException ex){
System.out.println(ex);
}
try(BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter toServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
){
toServer.write("Hello there!");
toServer.newLine();
toServer.flush();
while(!goodbye){
//if(fromServer.ready()) //culprit
msgFromServer = fromServer.readLine();
if(msgFromServer != null) {
System.out.println("Server: " + msgFromServer);
if(msgFromServer.equals("Bye"))
goodbye = true;
}
msgToServer = consoleInput.readLine();
if(msgToServer != null) {
toServer.write(msgToServer);
toServer.newLine();
toServer.flush();
if(msgToServer.equals("Bye"))
goodbye = true;
}
}
socket.close();
专注分享java语言的经验与见解,让所有开发者获益!
评论