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%的时间)会出现此错误。 当我尝试从服务器发送它时会发生这种情况:
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扩展了PacketToClient,当从objectinputstream接收时,它基本上只调用PacketToClient上的applyToClient。
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);
}
});
}
}
我从中做了很多研究,但我一直很冷淡。我偶尔也会获得Stream活动异常。
答案 0 :(得分:1)
我会说你在两个或多个线程中同时写入或读取流。这是&#39; stream active&#39;的唯一解释,它也可以解释另一个问题。
注意:您不需要以不同顺序创建流的业务。始终首先创建ObjectOutputStream。您应该在Runnable的run()方法中创建这些流,而不是在您执行此操作的位置:它涉及阻止I / O,这只应该在该线程中完成。