我有一个Netty服务器和一个Netty客户端,如果我以1秒的延迟发送数据包,则一切正常,但如果我彼此无延迟地发送3-4个数据包,则只有1-2个数据包到达客户端,我没收到,我的客户端数据包解码器:
public class PacketDecoader extends ByteToMessageDecoder {
@Getter
@Setter
private Decryption mode = Decryption.NONE;
@Getter
@Setter
private SecretKey AESKey;
@Override
protected synchronized void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
PacketSerializer packetSerializer = null;
System.out.println("Starting decoader for packet");
if(mode == Decryption.AES) {
packetSerializer = new
PacketSerializer(EncryptionUtills.dycryptWithAES(AESKey, msg));
}
if(mode == Decryption.NONE) {
packetSerializer = new PacketSerializer(msg);
}
long timestamp = packetSerializer.readVarLong();
System.out.println("TimeStamp " + timestamp);
if(System.currentTimeMillis() - timestamp > 2000) {
System.out.println("Warnig recived packet that was over 2 seconds to late");
return;
}
int id = packetSerializer.readVarInt();
System.out.println("Packet id " + id);
Class<? extends Packet> packetclass = NettyClient.getInstance().getPacketRegistry().getClassByID(id);
if(packetclass == null) {
System.out.println("No class found for packet with id " + id);
return;
}
Packet packet = packetclass.newInstance();
packet.Read(packetSerializer);
if(packetSerializer.getBuf().readableBytes() > 0) {
System.out.println("Having " + packetSerializer.readableBytes() +" more bytes then red!");
}
out.add(packet);
}
public enum Decryption{
AES,
NONE;
}
服务器Encoader:
public class PacketEncoader extends MessageToByteEncoder<Packet>{
@Getter
@Setter
private Encryption mode = Encryption.NONE;
@Getter
@Setter
private SecretKey AESKey;
@Override
protected void encode(ChannelHandlerContext ctx, Packet msg, ByteBuf out) throws Exception {
int id = NettyServer.getInstance().getPacketRegistry().getIdForPacket(msg);
if(id == -1) {
System.out.println(Main.pr + "No id for packet " + msg.getClass().getName());
return;
}
PacketSerializer packetSerializer = new PacketSerializer(out.alloc().buffer());
packetSerializer.writeVarLong(System.currentTimeMillis());
packetSerializer.writeVarInt(id);
msg.Write(packetSerializer);
if(mode == Encryption.AES) {
out.writeBytes(EncryptionUtills.encryptWithAES(AESKey, packetSerializer.getBuf()));
}
if(mode == Encryption.NONE) {
out.writeBytes(packetSerializer.getBuf());
}
System.out.println("Encoded packet " + msg.getClass().getSimpleName() + " with size " + packetSerializer.writerIndex());
}
public enum Encryption{
AES,
NONE;
}
有没有我忽略的错误?
EncryptionUtills类:
public class EncryptionUtills {
public static ByteBuf decryptWithRSA(ByteBuf encrypted, PrivateKey mykey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, mykey);
return wrightbytes(encrypted.alloc().buffer(), cipher.doFinal(readbytes(encrypted)));
}
public static ByteBuf encryptWithRSA(ByteBuf encrypted, PublicKey mykey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, mykey);
return wrightbytes(encrypted.alloc().buffer(), cipher.doFinal(readbytes(encrypted)));
}
public static ByteBuf encryptWithAES(SecretKey key, ByteBuf message) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
return wrightbytes(message.alloc().buffer(), cipher.doFinal(readbytes(message)));
}
public static ByteBuf dycryptWithAES(SecretKey key, ByteBuf message) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
return wrightbytes(message.alloc().buffer(), cipher.doFinal(readbytes(message)));
}
public static boolean isKeyPairValid(String filename) {
File file = new File(Main.instance.getDataFolder(), filename + ".key");
File file2 = new File(Main.instance.getDataFolder(), filename + ".pub");
return file.exists() && file2.exists();
}
public static KeyPair generateSSLKeyPair(int size, String outfile) throws Exception{
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(size);
KeyPair kp = kpg.generateKeyPair();
Key pub = kp.getPublic();
Key pvt = kp.getPrivate();
Base64.Encoder encoder = Base64.getEncoder();
Writer out = new FileWriter(new File(Main.instance.getDataFolder(), outfile + ".key"));
out.write("-----BEGIN RSA PRIVATE KEY-----\n");
out.write(encoder.encodeToString(pvt.getEncoded()));
out.write("\n-----END RSA PRIVATE KEY-----\n");
out.close();
out = new FileWriter(new File(Main.instance.getDataFolder(), outfile + ".pub"));
out.write("-----BEGIN RSA PUBLIC KEY-----\n");
out.write(encoder.encodeToString(pub.getEncoded()));
out.write("\n-----END RSA PUBLIC KEY-----\n");
out.close();
return kp;
}
public static KeyPair readKeys(File keys) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
Path path = Paths.get(keys + ".key");
List<String> lines = Files.readAllLines(path);
byte[] bytes = decoder.decode(lines.get(1));
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey pvt = kf.generatePrivate(ks);
Path path2 = Paths.get(keys + ".pub");
List<String> lines2 = Files.readAllLines(path2);
byte[] bytes2 = decoder.decode(lines2.get(1));
/* Generate public key. */
X509EncodedKeySpec ks2 = new X509EncodedKeySpec(bytes2);
KeyFactory kf2 = KeyFactory.getInstance("RSA");
PublicKey pub = kf2.generatePublic(ks2);
return new KeyPair(pub, pvt);
}
public static SecretKey generateAESKey(int size) throws NoSuchAlgorithmException {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(size);
return kgen.generateKey();
}
private static ByteBuf wrightbytes(ByteBuf wright, byte[] data) {
int i = 0;
while (i < data.length) {
wright.writeByte(data[i]);
i++;
}
return wright;
}
private static byte[] readbytes(ByteBuf buf) {
int k = buf.readableBytes();
byte[] data = new byte[k];
int i = 0;
while (i < k) {
data[i] = buf.readByte();
i++;
}
return data;
}
// The higher the number of iterations the more
// expensive computing the hash is for us and
// also for an attacker.
private static final int iterations = 20*1000;
private static final int saltLen = 32;
private static final int desiredKeyLen = 256;
/** Computes a salted PBKDF2 hash of given plaintext password
suitable for storing in a database.
Empty passwords are not supported. */
public static String getSaltedHash(String password) throws Exception {
byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
// store the salt with the password
return org.apache.commons.codec.binary.Base64.encodeBase64String(salt) + "$" + hash(password, salt);
}
/** Checks whether given plaintext password corresponds
to a stored salted hash of the password. */
public static boolean check(String password, String stored) throws Exception{
String[] saltAndPass = stored.split("\\$");
if (saltAndPass.length != 2) {
throw new IllegalStateException(
"The stored password have the form 'salt$hash'");
}
String hashOfInput = hash(password, org.apache.commons.codec.binary.Base64.decodeBase64(saltAndPass[0]));
return hashOfInput.equals(saltAndPass[1]);
}
// using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
// cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
private static String hash(String password, byte[] salt) throws Exception {
if (password == null || password.length() == 0)
throw new IllegalArgumentException("Empty passwords are not supported.");
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey key = f.generateSecret(new PBEKeySpec(
password.toCharArray(), salt, iterations, desiredKeyLen)
);
return org.apache.commons.codec.binary.Base64.encodeBase64String(key.getEncoded());
}
}
如果有人知道如何解决这个问题,请告诉我