输入/输出流遇到另一个问题。在这里,我将数据从服务器发送到客户端。在发送数据之前,服务器会发送一个小字符串,只是要告诉客户端他将发送的内容,因此客户端知道他应该使用哪个函数来接收。
我很好地接收了第一个字符串,但是随后我没有得到好的整数,之后我收到的第二个字符串为“ 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,但是不可读。
有什么建议吗?
答案 0 :(得分:1)
在这种情况下,发送二进制数据时,请完全使用DataOutputStream。 (或者,您可以输入文字。)
private static DataOutputStream out;
out = new DataOutputStream(clientSocket.getOutputStream());
public static void sendType(String type) {
out.writeUTF(type);
out.flush();
}
冲洗对于二进制对话很重要。
包装类DataOutputStream,Printer,BufferedReader等的问题是它们启动了自己的“游标”,并会在关闭时自行关闭包装的I / O。拥有几个DataOutputStreams有点令人担忧。至少与预期不符。
按照我的正常模式在main
:new Server().exec();
中进行操作。
那将删除所有这些静态变量。