package com.common.net;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Random;
public abstract class PacketCommunicator implements Runnable {
private Object lastCommandSent;
private Object lastCommandReceived;
private Object lastPacketReceived;
private Object lastPacketSent;
protected ObjectInputStream in;
protected ObjectOutputStream out;
protected Socket socket;
private boolean connected;
protected boolean encryptionEnabled = false;
protected String key = "default";
public HashMap<String, Object> data;
protected int sentPackets = 0;
protected int receivedPackets = 0;
public String getIP() {
return socket.getInetAddress().toString();
}
public abstract void disconnect();
public abstract void broadcast(String cmd, String data);
public abstract void broadcast(Object packet);
/**
* This is used for the LPacket system which is not recommended for
* sensitive data since LPacket's can be decompiled and the functions for
* both server and client are visible.
*
* @param packet
*/
public abstract void packetReceived(Object packet);
/**
* This is good for sensitive data
*
* @param packetID
* ID of packet
* @param cmd
* Labeling command
* @param data
*/
public abstract void packetReceived(String cmd, String data);
public void toggleEncryption() {
encryptionEnabled = !encryptionEnabled;
}
public boolean isConnected() {
return connected;
}
public void flush() {
try {
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Sends the LPacket to this client
*
* @param packet
*/
public void sendPacket(Object packet) {
try {
sentPackets++;
out.flush();
out.writeObject(packet);
this.lastPacketSent = packet;
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendPacket(String cmd, String data) {
try {
sentPackets++;
String s = cmd + ":" + sentPackets + "::" + data;
out.flush();
if (encryptionEnabled) {
out.writeObject(encrypt(key, s));
} else {
out.writeObject(s);
}
out.flush();
lastCommandSent = s;
} catch (IOException e) {
e.printStackTrace();
}
}
// Constructor class for game client
public PacketCommunicator(String server, int port) throws IOException {
this(new Socket(server, port), false);
}
/**
*
* @param socket
* @param onServer
* The Packet Communicator on the server MUST create the input
* stream first This constructor is used for the server
*/
public PacketCommunicator(Socket socket, boolean onServer) {
this.socket = socket;
data = new HashMap<String, Object>();
try {
if (onServer) {
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
} else {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
}
connected = true;
} catch (IOException e) {
e.printStackTrace();
}
Thread t = new Thread(this);
t.start();
}
/*
* @param Manually closes the connection
*/
public void closeConnection() {
connected = false;
disconnect();
try {
out.flush();
out.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (this.isConnected()) {
try {
Object packet = in.readObject(); <---Line 174
receivedPackets++;
if (packet instanceof String) {
this.lastCommandReceived = packet;
String packetString = packet.toString();
if (encryptionEnabled) {
packetString = decrypt(key, packetString);
}
String cmd = packetString.substring(0, packetString.indexOf(":"));
int packetID = Integer.parseInt(packetString.substring(packetString.indexOf(":") + 1,
packetString.indexOf("::")));
String data = packetString.substring(packetString.indexOf("::") + 2);
// FServer.log(packetString);
if (packetID == receivedPackets) {
} else {
}
packetReceived(cmd, data);
} else {
this.lastPacketReceived = packet;
this.packetReceived(packet);
}
} catch (StreamCorruptedException e) {
connected = false;
e.printStackTrace();
} catch (EOFException e) {
// This usually happens when someone manually disconnects,
// really not too big of an issue
connected = false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SocketException e) {
// Closed client
connected = false;
} catch (IOException e) {
connected = false;
e.printStackTrace();
}
}
System.out.println("Last packet sent: " + lastPacketSent);
System.out.println("Last packet received: " + lastPacketReceived);
System.out.println("Last command sent: " + lastCommandSent);
System.out.println("Last command received: " + lastCommandReceived);
disconnect();
}
public static String encrypt(String key, String text) {
long finalKey = 0;
for (int i = 0; i < key.length(); i++) {
long tempKey = key.charAt(i);
tempKey *= 128;
finalKey += tempKey;
}
Random generator = new Random(finalKey);
String returnString = "";
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == ' ') {
returnString += text.charAt(i);
} else {
int temp = text.charAt(i);
temp += generator.nextInt(95);
if (temp > 126) {
temp -= 95;
}
returnString += (char) temp;
}
}
return returnString;
}
public static String decrypt(String key, String text) {
long finalKey = 0;
for (int i = 0; i < key.length(); i++) {
long tempKey = key.charAt(i);
tempKey *= 128;
finalKey += tempKey;
}
Random generator = new Random(finalKey);
String returnString = "";
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == ' ') {
returnString += text.charAt(i);
} else {
int temp = text.charAt(i);
temp -= generator.nextInt(95);
if (temp < 36) {
temp += 95;
}
if (temp > 126) {
temp -= 95;
}
returnString += (char) temp;
}
}
return returnString;
}
}
java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.refill(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.read(Unknown Source)
at java.io.DataInputStream.readInt(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readInt(Unknown Source)
at java.io.ObjectInputStream.readInt(Unknown Source)
at java.util.ArrayList.readObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.common.net.PacketCommunicator.run(PacketCommunicator.java:174)
at java.lang.Thread.run(Unknown Source)
기본적으로, 때때로. 그리고 때로는 (시간의 25 %)이 오류가 나타나기 만한다는 것을 의미합니다.스트림 손상된 예외 잘못된 코드 : 00
public void teleportToMap(String mapName, int tileX, int tileY) {
player.map = mapName;
currentMap = Server.mapHandler.getMap(mapName);
MapPacket mp = new MapPacket(currentMap, tileX, tileY);
sendPacket(mp);
}
을 그리고 지금 여기 MapPacket의 조각이다 : 나는 서버에서이를 보내려고 할 때 이 발생합니다. MapPacket은 기본적으로 objectinputstream으로부터받은 경우 PacketToClient에서 단지 applyToClient를 호출하는 PacketToClient를 확장합니다.
package com.common.packet.packets.client;
import com.badlogic.gdx.Gdx;
import com.client.Forest;
import com.client.net.ServerConnection;
import com.client.scenes.GameScene;
import com.common.map.Map;
import com.common.movable.Movable;
import com.common.packet.PacketToClient;
import java.util.ArrayList;
public class MapPacket extends PacketToClient {
private static final long serialVersionUID = 1L;
String mapName;
ArrayList<Movable> ground;
int tileX, tileY;
public MapPacket(Map map, int tileX, int tileY) {
this.mapName = map.name;
this.ground = map.getGround();
this.tileX = tileX;
this.tileY = tileY;
}
@Override
public void applyPacketToClient(ServerConnection server) {
Gdx.app.postRunnable(new Runnable() {
public void run() {
GameScene.currentMap = null;
GameScene.mapRenderer.setCurrentMap(null);
Map map = ServerConnection.loadMapFromServer(mapName);
map.setGround(ground);
GameScene.mapRenderer.setCurrentMap(map);
GameScene.currentMap = map;
Forest.player.setTilePosition(tileX, tileY);
}
});
}
}
나는 이것에 대해 많은 연구를했지만, 계속 감기에 걸렸다. 또한 때로는 스트림 활성 예외가 발생합니다.
아. 괜찮아. 그것은 당신의 아이디어가 StreamCorruptedException을 제거한 것처럼 보입니다. (또는 그렇게 보일 수도 있습니다. 가끔씩 만 발생하기 때문에 이걸로 말하기가 어렵습니다.) 패킷을 보낼 때 어떨까요? 나도 항상 스레드에서 그렇게해야합니까? – Buzzyboy
이론적으로 패킷을 보내는 PacketCommunicator에 다른 스레드를 만들 수 있습니다. sendPacket가 호출되면 Packet을 버퍼 배열에 추가합니다. 전송할 항목이 없을 때까지 루프를 반복하고 더 추가 될 때까지 기다립니다. 이게 합리적일까요? – Buzzyboy
아. 나는 지금 본다. writeObject 전에 현재 스레드의 이름을 인쇄하기로 결정했다. 그것에 쓰는 3 개의 쓰레드가있다. 정말 고맙습니다! – Buzzyboy