除非流关闭,否则 BufferedWriter 不会发送文本
我有一个与客户端通信的服务器。
服务器是多线程的,当从套接字读取的第一行是“请求”时,该线程是使用套接字和连接到套接字的 bufferedreader 创建的:
public class scriptComm implements Runnable {
private Socket sock;
private Socket sock2;
private Connection connection;
private BufferedReader reader;
@Override
public void run() {
try {
String name = reader.readLine();
String password = reader.readLine();
String line;
connection = methods.connectToDatabase();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
if (connection != null && name != null && password != null) {
try {
ResultSet rs = connection.createStatement().executeQuery(
"SELECT name, password, doupdate FROM accounts "
+ "WHERE name = '" + name + "' AND doupdate = 'yes'"
+ " AND password = '" + password + "'");
if (rs.next()) {
methods.log("worked");
bw.write("accept");
bw.flush();
bw.close();
reader = new BufferedReader(new InputStreamReader(sock2.getInputStream()));
if ((line = reader.readLine()) != null) {
mainFrame.jTextArea1.append("line \n");
connection.createStatement().executeUpdate(
"UPDATE accounts SET updatetext = '" + line + "' "
+ "WHERE name = '" + name + "'");
}else{
mainFrame.jTextArea1.append("No text received \n");
}
} else {
bw.write("decline");
bw.flush();
}
bw.close();
rs.close();
} catch (SQLException ex) {
methods.log("Error when executing statement in scriptComm");
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
methods.log("missing values in scriptComm");
}
} catch (IOException ex) {
}
}
public scriptComm(Socket sock, BufferedReader reader) {
this.sock = sock;
this.sock2 = sock;
this.reader = reader;
}}
您可能会注意到,我在写入“接受”后关闭了 bw 流。
这是因为当流未关闭时,客户端只是挂在那里,就好像它没有接收到任何输入一样。
客户端:
try{
String line;
Socket sock = new Socket("myipaddresshere",portnumber);
PrintWriter writer = new PrintWriter(sock.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
writer.println("script");
writer.flush();
writer.println(jTextField1.getText());
writer.flush();
writer.println(jTextField2.getText());
writer.flush();
if ((reader.readLine()).equals("accept")) {
writer.write("testing123");
writer.flush();
writer.close();
} else {
jTextArea1.append("fail");
}
reader.close();
writer.close();
}catch(IOException e){
jTextArea1.append("Server not available. Please try again later.");
}
当从服务器写入“accept”后流未关闭时,就好像客户端只是坐在 if(reader.readLine().equals("accept")) 布尔检查处(是的,流被刷新服务器端)。
但是,当流也在服务器端关闭时,它会通过布尔检查并继续将行“testing123”写入流。服务器显然无法读取这一行,因为当 BufferedReader 关闭时套接字流也被关闭。您可能会注意到,我尝试通过简单地创建另一个名为 sock2 的变量来复制套接字,但似乎此连接也关闭了(有意义)。
注意:当使用错误的用户/密码连接时(即当 rs.next() 返回 false 时),它会向流中写入“拒绝”,并且客户端会收到此消息。
对这个真的很困惑..
谢谢, 麦克风。
I have a server that communicates with a client.
The server is multithreaded, and this thread is created with the socket and a bufferedreader connected to the socket, when the first line read from the socket is "request":
public class scriptComm implements Runnable {
private Socket sock;
private Socket sock2;
private Connection connection;
private BufferedReader reader;
@Override
public void run() {
try {
String name = reader.readLine();
String password = reader.readLine();
String line;
connection = methods.connectToDatabase();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
if (connection != null && name != null && password != null) {
try {
ResultSet rs = connection.createStatement().executeQuery(
"SELECT name, password, doupdate FROM accounts "
+ "WHERE name = '" + name + "' AND doupdate = 'yes'"
+ " AND password = '" + password + "'");
if (rs.next()) {
methods.log("worked");
bw.write("accept");
bw.flush();
bw.close();
reader = new BufferedReader(new InputStreamReader(sock2.getInputStream()));
if ((line = reader.readLine()) != null) {
mainFrame.jTextArea1.append("line \n");
connection.createStatement().executeUpdate(
"UPDATE accounts SET updatetext = '" + line + "' "
+ "WHERE name = '" + name + "'");
}else{
mainFrame.jTextArea1.append("No text received \n");
}
} else {
bw.write("decline");
bw.flush();
}
bw.close();
rs.close();
} catch (SQLException ex) {
methods.log("Error when executing statement in scriptComm");
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
methods.log("missing values in scriptComm");
}
} catch (IOException ex) {
}
}
public scriptComm(Socket sock, BufferedReader reader) {
this.sock = sock;
this.sock2 = sock;
this.reader = reader;
}}
You may notice that I close the bw stream after it writes "accept".
This is due to the client simply hanging there, as if it doesn't receive any input, when the stream is not closed.
The client:
try{
String line;
Socket sock = new Socket("myipaddresshere",portnumber);
PrintWriter writer = new PrintWriter(sock.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
writer.println("script");
writer.flush();
writer.println(jTextField1.getText());
writer.flush();
writer.println(jTextField2.getText());
writer.flush();
if ((reader.readLine()).equals("accept")) {
writer.write("testing123");
writer.flush();
writer.close();
} else {
jTextArea1.append("fail");
}
reader.close();
writer.close();
}catch(IOException e){
jTextArea1.append("Server not available. Please try again later.");
}
When the stream is not closed after writing "accept" from the server, it's as if the client just sits at the if(reader.readLine().equals("accept")) boolean check ( and yes, the stream is flushed server-side ).
However, when the stream is also closed server-side, it passes the boolean check and continues on to write the line "testing123" to the stream. The server can obviously not read this line as the socket stream was closed when the BufferedReader closed. As you may notice, I tried replicating the socket by simply creating another variable called sock2, but it seems this connection closes as well (makes sense).
Note: when connecting with a wrong user/pass (i.e. when rs.next() returns false), it does write "decline" to the stream and the client gets this.
Really confused about this one..
Thanks,
Mike.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
请注意,写入不会写入换行符,并且您正在尝试读取整行。在刷新之前您需要编写一个换行符。
编辑器使用 BufferedWriter。newLine() 或将
"\n"
附加到您编写的字符串中。Note, a write doesn't write a newline, and you are trying to read whole lines. You need to write a newline character before you flush.
Edither use BufferedWriter.newLine() or append
"\n"
to the strings that you write.我将保留这一点并提出一条建议:
当您想要将字符写入流时,您应该始终使用具有显式字符编码的
OutputStreamWriter
和InputStreamReader
。我推荐“UTF-8”。正如所写的,您的代码将使用平台默认编码进行写入和读取。这将一直有效,直到您在中国有人在 Windows 上运行客户端,在美国有人在 Linux 上运行服务器(并且根据您发送的内容,它可能会更快崩溃)。
I'll leave this retracted with a piece of advice:
When you want to write characters to a stream, you should always use an
OutputStreamWriter
andInputStreamReader
with an explicit character encoding. I recommend "UTF-8".As written, your code will both write and read with the platform-default encoding. Which will work, right up until the time you have someone in China running the client on Windows, with someone in the US running the server on Linux (and depending on what you're sending, it could break much sooner).