DataOutputStream 仅在 System.out.println 之前有效
DataOutputStream works only preceded by System.out.println
我在 input/output 流中遇到了另一个问题。在这里,我将数据从服务器发送到客户端。在发送数据之前,服务器发送一个小字符串来告诉客户端他将发送什么,这样客户端就知道他应该使用哪个函数来接收。
我很好地接收了第一个字符串,但后来我没有得到正确的整数,之后我收到的第二个字符串是 "null"。
此外,如果我在将 DataOutputStream 与 dos.writeInt 一起使用之前执行 System.out.println,则一切正常。
我不明白。这是代码:
服务器:
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;
public class Server {
private static OutputStream out;
static byte[] generateRandomBytes(int len) {
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[len];
random.nextBytes(bytes);
return bytes;
}
public static void sendType(String type) {
PrintWriter textWriter = new PrintWriter(out);
textWriter.println(type);
textWriter.flush();
}
public static void sendKeyNumber(int keyNumber) {
sendType("keyNumber");
try {
DataOutputStream dos = new DataOutputStream(out);
//System.out.println("Sending key number: " + keyNumber);
dos.writeInt(keyNumber);
//dos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void sendKey(byte[] key) {
sendType("key");
try {
DataOutputStream dos = new DataOutputStream(out);
//System.out.println("key length to send: " +key.length);
dos.writeInt(key.length); // write length of the byte array
//dos.flush();
dos.write(key);
//dos.flush();
System.out.println("key send: " +key);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket clientSocket ;
System.out.println("ouverture du server");
try {
ServerSocket serverSocket = new ServerSocket(2004);
clientSocket = serverSocket.accept();
out = clientSocket.getOutputStream();
sendKeyNumber(0);
byte[] keyBytes = generateRandomBytes(32);
sendKey(keyBytes);
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.crypto.spec.SecretKeySpec;
public class Main {
static InputStream in;
public static int receiveKeyNumber() {
DataInputStream dis = new DataInputStream(in);
int keyNumber = 0;
try {
keyNumber = dis.readInt();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return keyNumber;
}
public static SecretKeySpec receiveKey() {
DataInputStream dIn = new DataInputStream(in);
int length;
byte[] keyBytes = null;
try {
length = dIn.readInt(); // read length of incoming message
System.out.println("key length: " + length);
if(length!=32) {
System.err.println("Incorrect size for key: "+ length);
}
else {
keyBytes = new byte[length];
dIn.readFully(keyBytes, 0, keyBytes.length);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SecretKeySpec aesKey = new SecretKeySpec(keyBytes, "AES");
return aesKey;
}
public static void main(String[] args) {
Socket clientSocket;
try {
clientSocket = new Socket(InetAddress.getLocalHost(),2004);
in = clientSocket.getInputStream();
while(!clientSocket.isClosed()) {
BufferedReader textReader = new BufferedReader(new InputStreamReader(in));
String type = textReader.readLine();
System.out.println(type);
if(type.equals("keyNumber")) {
int KN = receiveKeyNumber();
System.out.println(KN);
}
if(type.equals("key")) {
SecretKeySpec key = receiveKey();
System.out.println(key);
}
}
clientSocket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这是我不执行 System.out.println 时(在客户端控制台中)得到的结果:
keyNumber
1801812234
null
我总是得到同样奇怪的数字;我尝试将其转换为 ASCII,但它不可读。
有什么建议吗?
在发送二进制数据的情况下,请完全使用 DataOutputStream。
(或者你可以去文本。)
private static DataOutputStream out;
out = new DataOutputStream(clientSocket.getOutputStream());
public static void sendType(String type) {
out.writeUTF(type);
out.flush();
}
刷新对于二元对话很重要。
包装 类 DataOutputStream、Printer、BufferedReader 等的问题在于它们会启动自己的 "cursor" 并会在自己关闭时关闭包装的 I/O。拥有多个 DataOutputStreams 有点令人担忧;至少不是预期的那样。
顺便说一下,我的正常模式是 main
: new Server().exec();
之类的。
这将消除所有这些静电。
我在 input/output 流中遇到了另一个问题。在这里,我将数据从服务器发送到客户端。在发送数据之前,服务器发送一个小字符串来告诉客户端他将发送什么,这样客户端就知道他应该使用哪个函数来接收。
我很好地接收了第一个字符串,但后来我没有得到正确的整数,之后我收到的第二个字符串是 "null"。
此外,如果我在将 DataOutputStream 与 dos.writeInt 一起使用之前执行 System.out.println,则一切正常。 我不明白。这是代码:
服务器:
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;
public class Server {
private static OutputStream out;
static byte[] generateRandomBytes(int len) {
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[len];
random.nextBytes(bytes);
return bytes;
}
public static void sendType(String type) {
PrintWriter textWriter = new PrintWriter(out);
textWriter.println(type);
textWriter.flush();
}
public static void sendKeyNumber(int keyNumber) {
sendType("keyNumber");
try {
DataOutputStream dos = new DataOutputStream(out);
//System.out.println("Sending key number: " + keyNumber);
dos.writeInt(keyNumber);
//dos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void sendKey(byte[] key) {
sendType("key");
try {
DataOutputStream dos = new DataOutputStream(out);
//System.out.println("key length to send: " +key.length);
dos.writeInt(key.length); // write length of the byte array
//dos.flush();
dos.write(key);
//dos.flush();
System.out.println("key send: " +key);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket clientSocket ;
System.out.println("ouverture du server");
try {
ServerSocket serverSocket = new ServerSocket(2004);
clientSocket = serverSocket.accept();
out = clientSocket.getOutputStream();
sendKeyNumber(0);
byte[] keyBytes = generateRandomBytes(32);
sendKey(keyBytes);
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.crypto.spec.SecretKeySpec;
public class Main {
static InputStream in;
public static int receiveKeyNumber() {
DataInputStream dis = new DataInputStream(in);
int keyNumber = 0;
try {
keyNumber = dis.readInt();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return keyNumber;
}
public static SecretKeySpec receiveKey() {
DataInputStream dIn = new DataInputStream(in);
int length;
byte[] keyBytes = null;
try {
length = dIn.readInt(); // read length of incoming message
System.out.println("key length: " + length);
if(length!=32) {
System.err.println("Incorrect size for key: "+ length);
}
else {
keyBytes = new byte[length];
dIn.readFully(keyBytes, 0, keyBytes.length);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SecretKeySpec aesKey = new SecretKeySpec(keyBytes, "AES");
return aesKey;
}
public static void main(String[] args) {
Socket clientSocket;
try {
clientSocket = new Socket(InetAddress.getLocalHost(),2004);
in = clientSocket.getInputStream();
while(!clientSocket.isClosed()) {
BufferedReader textReader = new BufferedReader(new InputStreamReader(in));
String type = textReader.readLine();
System.out.println(type);
if(type.equals("keyNumber")) {
int KN = receiveKeyNumber();
System.out.println(KN);
}
if(type.equals("key")) {
SecretKeySpec key = receiveKey();
System.out.println(key);
}
}
clientSocket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这是我不执行 System.out.println 时(在客户端控制台中)得到的结果:
keyNumber
1801812234
null
我总是得到同样奇怪的数字;我尝试将其转换为 ASCII,但它不可读。
有什么建议吗?
在发送二进制数据的情况下,请完全使用 DataOutputStream。 (或者你可以去文本。)
private static DataOutputStream out;
out = new DataOutputStream(clientSocket.getOutputStream());
public static void sendType(String type) {
out.writeUTF(type);
out.flush();
}
刷新对于二元对话很重要。
包装 类 DataOutputStream、Printer、BufferedReader 等的问题在于它们会启动自己的 "cursor" 并会在自己关闭时关闭包装的 I/O。拥有多个 DataOutputStreams 有点令人担忧;至少不是预期的那样。
顺便说一下,我的正常模式是 main
: new Server().exec();
之类的。
这将消除所有这些静电。