I've programmed the following client-server pair to set up a very simplified version of an IPSec-connection (Cryptography-related).
The problem is, that on the second call to readObject(), i.e.:
// Receive finished message from server
finishedMessage = (BigInteger) inputStream.readObject();
I get a java.io.EOFException.
It should be said, that on most runs the EOFException is thrown, but on some runs it runs flawlessly ?
I've been debugging for hours now, but can't find the error.
If anyone can see the error, please let me know - I will appreciate it !
Error message:
[CLIENT]: Connected...
[CLIENT]: Common key = 33569
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at IPSecClient.SetupSSLConnection(IPSecClient.java:68)
at IPSecClient.main(IPSecClient.java:116)
Client:
import java.math.BigInteger;
import java.net.*;
import java.util.ArrayList;
import java.util.Random;
import java.io.*;
public class IPSecClient {
private Socket socket;
private ObjectInputStream inputStream;
private ObjectOutputStream outputStream;
private IPSec gen;
private ArrayList<BigInteger[]> messages;
private BigInteger[] message;
private final int port, numBits;
private String address;
private Random rand;
private int fixedNumber;
private BigInteger fixedPrime, fixedBase, partialKeyClient,
partialKeyServer, commonKey, publicKeyServer, modulusServer;
public IPSecClient() {
rand = new Random();
numBits = 256;
fixedNumber = rand.nextInt(1000);
fixedPrime = new BigInteger("51803");
fixedBase = new BigInteger("3");
gen = new IPSec();
gen.KeyGen(numBits);
messages = new ArrayList<BigInteger[]>();
port = 5000;
address = "localhost";
}
public void SetupSSLConnection() {
try {
socket = new Socket(address, port);
outputStream = new ObjectOutputStream(socket.getOutputStream());
inputStream = new ObjectInputStream(socket.getInputStream());
System.out.println("[CLIENT]: Connected...");
// Send partial key and certificate (public key) to server
partialKeyClient = fixedBase.pow(fixedNumber).mod(fixedPrime);
message = new BigInteger[] {partialKeyClient, gen.PublicKey(), gen.Modulus()};
messages.add(message);
outputStream.writeObject(message);
outputStream.flush();
// Receive partial key and certificate from server
message = (BigInteger[]) inputStream.readObject();
messages.add(message);
partialKeyServer = message[0];
publicKeyServer = message[1];
modulusServer = message[2];
// Generate common key
commonKey = partialKeyServer.pow(fixedNumber).mod(fixedPrime);
System.out.println("[CLIENT]: Common key = " + commonKey.intValue());
// Send finished message
BigInteger accumulatedMessages = AccumulateMessages(messages).mod(gen.PublicKey());
BigInteger finishedMessage = gen.GenerateRSASignature(accumulatedMessages);
outputStream.writeObject(finishedMessage);
outputStream.flush();
// Receive finished message from server
finishedMessage = (BigInteger) inputStream.readObject();
// Verify finished message
boolean result = gen.VerifyRSASignature(AccumulateMessages(messages).mod(publicKeyServer), finishedMessage, publicKeyServer, modulusServer);
System.out.println("[CLIENT]: Verification of finished message " + (result ? "succeeded" : "failed"));
if (!result) {
System.out.println("[CLIENT]: SSL-connection could not be estasblished...");
CloseConnection(-1);
}
System.out.println("[CLIENT]: SSL-connection estasblished...");
CloseConnection(0);
} catch (SocketException se) {
se.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void CloseConnection(int exitCode) {
try {
socket.close();
outputStream.close();
inputStream.close();
System.exit(exitCode);
} catch (IOException e) {
e.printStackTrace();
}
}
private BigInteger AccumulateMessages(ArrayList<BigInteger[]> messages) {
BigInteger accumulator = new BigInteger("0");
for (BigInteger[] message : messages)
{
for (BigInteger part : message)
{
accumulator = accumulator.add(part);
}
}
return accumulator;
}
public static void main(String[] args) {
IPSecClient client = new IPSecClient();
client.SetupSSLConnection();
}
}
Server:
import java.io.*;
import java.math.BigInteger;
import java.net.*;
import java.util.ArrayList;
import java.util.Random;
public class IPSecServer {
private ServerSocket serverSocket;
private Socket socket;
private ObjectInputStream inputStream;
private ObjectOutputStream outputStream;
private IPSec gen;
private ArrayList<BigInteger[]> messages;
private BigInteger[] message;
private final int port;
private Random rand;
private int fixedNumber;
private BigInteger fixedPrime, fixedBase, partialKeyClient,
partialKeyServer, commonKey, publicKeyClient, modulusClient;
public IPSecServer() {
rand = new Random();
fixedNumber = rand.nextInt(1000);
fixedPrime = new BigInteger("51803");
fixedBase = new BigInteger("3");
gen = new IPSec();
gen.KeyGen(2048);
messages = new ArrayList<BigInteger[]>();
port = 5000;
}
public void SetupSSLConnection() {
try {
serverSocket = new ServerSocket(port);
System.out.println("[SERVER]: Listening...");
socket = serverSocket.accept();
inputStream = new ObjectInputStream(socket.getInputStream());
outputStream = new ObjectOutputStream(socket.getOutputStream());
System.out.println("[SERVER]: Connected... " + "Port/IP: " + socket.getPort() + socket.getInetAddress());
// Receive partial key and certificate from client
message = (BigInteger[]) inputStream.readObject();
messages.add(message);
partialKeyClient = message[0];
publicKeyClient = message[1];
modulusClient = message[2];
// Send partial key and certificate to client
partialKeyServer = fixedBase.pow(fixedNumber).mod(fixedPrime);
message = new BigInteger[] {partialKeyServer, gen.PublicKey(), gen.Modulus()};
messages.add(message);
outputStream.writeObject(message);
outputStream.flush();
// Generate common key
commonKey = partialKeyClient.pow(fixedNumber).mod(fixedPrime);
System.out.println("[SERVER]: Common key = " + commonKey.intValue());
// Receive finished message from client
BigInteger finishedMessage = (BigInteger) inputStream.readObject();
messages.add(new BigInteger[] {finishedMessage});
// Verify finished message
boolean result = gen.VerifyRSASignature(AccumulateMessages(messages).mod(publicKeyClient), finishedMessage, publicKeyClient, modulusClient);
System.out.println("[SERVER]: Verification of finished message " + (result ? "succeeded" : "failed"));
if (!result) {
System.out.println("[SERVER]: SSL-connection could not be estasblished...");
CloseConnection(-1);
}
// Send finished message to client
BigInteger accumulatedMessages = AccumulateMessages(messages).mod(gen.PublicKey());
finishedMessage = gen.GenerateRSASignature(accumulatedMessages);
outputStream.writeObject(finishedMessage);
outputStream.flush();
System.out.println("[SERVER]: SSL-connection estasblished...");
CloseConnection(0);
} catch (SocketException se) {
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void CloseConnection(int exitCode) {
try {
socket.close();
outputStream.close();
inputStream.close();
serverSocket.close();
System.exit(exitCode);
} catch (IOException e) {
e.printStackTrace();
}
}
private BigInteger AccumulateMessages(ArrayList<BigInteger[]> messages) {
BigInteger accumulator = new BigInteger("0");
for (BigInteger[] message : messages)
{
for (BigInteger part : message)
{
accumulator = accumulator.add(part);
}
}
return accumulator;
}
public static void main(String[] args) {
IPSecServer server = new IPSecServer();
server.SetupSSLConnection();
}
}
IPSec:
import java.math.BigInteger;
import java.util.Random;
import java.security.*;
public class IPSec {
private static final BigInteger one = new BigInteger("1");
// private key (n,d)
private BigInteger privateKey;
// public key (n,e)
private BigInteger publicKey = new BigInteger("3");
// modulus n
private BigInteger modulus;
public IPSec() {
}
// PUBLIC KEY
public BigInteger PublicKey() {
return publicKey;
}
public BigInteger Modulus() {
return modulus;
}
// KEY GENERATION
public void KeyGen(int keyLength) {
BigInteger p = BigInteger.probablePrime((int)Math.ceil(keyLength / 2), new Random());
BigInteger q = BigInteger.probablePrime((int)Math.ceil(keyLength / 2), new Random());
while (!(p.subtract(one)).gcd(publicKey).equals(one))
p = p.nextProbablePrime();
while (!(q.subtract(one)).gcd(publicKey).equals(one))
q = q.nextProbablePrime();
BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));
modulus = p.multiply(q);
privateKey = publicKey.modInverse(phi);
}
// ENCRYPT
public BigInteger Encrypt(BigInteger message) {
return message.modPow(publicKey, modulus);
}
public static BigInteger Encrypt(BigInteger message, BigInteger publicKey, BigInteger modulus) {
return message.modPow(publicKey, modulus);
}
// DECRYPT
public BigInteger Decrypt(BigInteger message) {
return message.modPow(privateKey, modulus);
}
// SIGNATURE GENERATION
// Generate RSA-signatures for a message
public BigInteger GenerateRSASignature(BigInteger message) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
return Decrypt(new BigInteger(1, digest.digest(message.toByteArray())).mod(Modulus()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.exit(-1);
}
return message;
}
// Verify RSA-signatures for a message
public boolean VerifyRSASignature(BigInteger message, BigInteger signature) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return (new BigInteger(1, digest.digest(message.toByteArray())).mod(Modulus())).equals(Encrypt(signature));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.exit(-1);
}
return false;
}
public boolean VerifyRSASignature(BigInteger message, BigInteger signature,
BigInteger publicKey, BigInteger modulus) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return (new BigInteger(1, digest.digest(message.toByteArray())).mod(Modulus())).equals(Encrypt(signature, publicKey, modulus));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.exit(-1);
}
return false;
}
public static void main(String[] args) {
Testing();
}
// MISC
public void printKeys() {
String s = "";
s += "public = " + publicKey + "\n";
s += "private = " + privateKey + "\n";
s += "modulus = " + modulus;
System.out.println(s);
}
public static void Testing() {
IPSec gen = new IPSec();
gen.KeyGen(128);
BigInteger message = new BigInteger("329");
System.out.println("Verify: " + gen.VerifyRSASignature(message, gen.GenerateRSASignature(message)));
}
}
Your server is barfing at the signature-verifying stage here:
if (!result) {
System.out.println("[SERVER]: SSL-connection could not be established...");
CloseConnection(-1);
}
and closing the socket without sending the FINISHED message. Check its output log. In such a case maybe you should send an error object first. Or else treat EOFException as a handshake failure.
NB:
For safety it is best to contruct the ObjectOutputStream before the ObjectInputStream at both ends.
You should close the ObjectOutputStream, not the socket, or the input stream. That way you can be sure it gets flushed. Closing any of the three closes the other two.
Don't call things 'SSL' when they aren't.
Related
I'm transferring Byte arrays of different kinds of files(.png, .txt, etc..) My socket starts sending the data and client starts receiving it. For some reason .pngs doesen't look same as they do on the server side. (Sometimes it says image is unreadable, sometimes only some parts of image are shown.. etc)? I'm wondering how could I make it so that the sent data would actually be the same as the sent data? Any suggestions what I'm doing wrong? (Note! If .png file has alpha channel, image seems always to be completely unreadable.)
Client side of the data transfer:
try
{
sInput = new ObjectInputStream(socket.getInputStream());
Input = socket.getInputStream();
}
catch (IOException eIO) {
System.out.println("Exception creating new Input/output Streams: " + eIO);
return false;
}
.
.
.
LoadCache[] filedata = (LoadCache[]) sInput.readObject(); //This contains the path and size of file
while(number < filedata.length){
byte[] mybytearray = new byte[(int) LoadCache.getSize(filedata[number])];
String result = Reader.UpdateCache(LoadCache.getPath(filedata[number]));
number++;
if(result != "skip" && result != "Stop"){
BufferedOutputStream Bos = new BufferedOutputStream(new FileOutputStream(result));
int BytesRead = Input.read(mybytearray, 0, mybytearray.length);
Bos.write(mybytearray, 0, BytesRead);
Bos.close();
}
}
Server side of the data transfer:
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
OutputStream Output;
BufferedInputStream buffIn;
.
.
.
try{
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
Output = socket.getOutputStream();
} catch (Exception e){
System.out.println("Couldn't create Input/Output streams");
}
.
.
.
File[] Data = Reader.getFiles(Action.getString(Incomingdata.getAction(datain)));
LoadCache LoadedCache[] = new LoadCache[Data.length];
for(int i = 0; i<Data.length; i++){
Path filePath = Paths.get(Data[i].getPath());
Path relativePath = base.relativize(filePath); //= filePath - base (so to say)
LoadedCache[i] = new LoadCache(relativePath.toString(), Data[i].length());
}
System.out.println(LoadedCache.length);
try {
sOutput.writeObject(LoadedCache);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for(File file : Data){
try {
if(file.isFile()){
byte[] bytearray = new byte[(int) file.length()];
buffIn = new BufferedInputStream(new FileInputStream(file));
buffIn.read(bytearray, 0, bytearray.length);
Output.write(bytearray, 0, bytearray.length);
Output.flush();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
buffIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Also! Now (I'm not quite sure anymore if I got this earlier) Client gives me java.util.zip.ZipException: incorrect header check -Exception (And none of the files is zipped)
Something Runnable:
Public class Client {
private ObjectInputStream sInput; // to read from the socket
private static ObjectOutputStream sOutput; // to write on the socket
private static Socket socket;
public static Client client;
public static Player player;
public static boolean loadingFiles;
String server;
int port;
boolean connected;
Client(String server, int port) {
this.server = server;
this.port = port;
this.connected = true;
}
public static boolean isConnected(Client client){
return client.connected;
}
private void disconnect() {
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {} // not much else I can do
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {} // not much else I can do
try{
if(socket != null) socket.close();
}
catch(Exception e) {} // not much else I can do
}
public boolean start() {
// try to connect to the server
try {
socket = new Socket(server, port);
}
// if it failed we catch the exception
catch(Exception ec) {
System.out.println("Error connecting to server: " + ec);
return false;
}
System.out.println("Connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
/* Creating Data Streams */
try
{
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
}
catch (IOException eIO) {
System.out.println("Exception creating streams: " + eIO);
return false;
}
// creates the Thread to listen from the server
new ListenFromServer().start();
String Cache;
if(Reader.ReadCache(Frame.drive +"//FM_Cache/version") == "WeHadToMakeNewFile"){ //If we don't have that file. We create it, but now it's empty.
Cache = "New";
}
else{ //If we do have cache and it has "version" we send our version to server.
Cache = Reader.ReadCache(Frame.drive +"FM_Cache/version");
}
send(new Incomingdata("", "", new Action(0, Cache, 0, 0)));
// success we inform the caller that it worked
return true;
}
public static void Connect() {
// default values
int portNumber = 16304;
String serverAddress = "0.0.0.0"; //I'm using my own ip here..
// create the Client object
client = new Client(serverAddress, portNumber);
// test if we can start the connection to the Server
if(client.start()){
client.connected = true;
}
}
public static void Disconnect(Client client) {
client.connected = false;
client.disconnect();
}
class ListenFromServer extends Thread {
public void run() {
loadingFiles = true;
while(true) {
try {
int number = 0;
LoadCache[] filedata = (LoadCache[]) sInput.readObject();
while(number < filedata.length){
byte[] mybytearray = new byte[(int) LoadCache.getSize(filedata[number])];
String result = Reader.UpdateCache(LoadCache.getPath(filedata[number]));
number++;
if(result != "skip" && result != "Stop"){
BufferedOutputStream Bos = new BufferedOutputStream(new FileOutputStream(result));
int BytesRead = sInput.read(mybytearray, 0, mybytearray.length);
Bos.write(mybytearray, 0, BytesRead);
Bos.close();
}
}
System.out.println("Cache has been patched succesfully!");
Client.loadingFiles = false;
}catch(EOFException e){
System.out.println("Problem reading the data streams! " +e);
break;
}
catch(IOException e) {
System.out.println(e);
break;
}
catch(ClassNotFoundException e2) {
}
}
}
}
public static void send(Incomingdata incomingdata) {
try {
sOutput.writeObject(incomingdata);
}
catch(IOException e) {
System.out.println("Exception writing to server: " + e);
}
}
}
Incomingdata:
package com.connection;
import com.connection.Action;
public class Incomingdata implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -1309997274550304156L;
private String Username, Password;
private Action action;
public Incomingdata(String Username, String Password, Action action){
this.Username = Username;
this.action = action;
this.Password = Password;
}
public static String getUsername(Incomingdata Incomingdata){
return Incomingdata.Username;
}
public static String getPassword(Incomingdata Incomingdata){
return Incomingdata.Password;
}
public static Action getAction(Incomingdata Incomingdata){
return Incomingdata.action;
}
}
LoadingCache:
package com.connection;
import java.io.Serializable;
public class LoadCache implements Serializable{
/**
*
*/
private static final long serialVersionUID = 7267682639705707967L;
String path;
long size;
public LoadCache(String path, long size){
this.path = path;
this.size = size;
}
public static long getSize(LoadCache cache) {
return cache.size;
}
public static String getPath(LoadCache filedata) {
return filedata.path;
}
}
Action.java:
package com.connection;
import com.connection.Action;
public class Action implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 4389420849399916526L;
int type, x, y;
String string;
public Action(int type, String string, int x, int y){
this.type = type;
this.string = string;
this.x = x;
this.y = y;
}
public static int getType(Action action) {
return action.type;
}
public static String getString(Action action) {
return action.string;
}
public static int getX(Action action) {
return action.x;
}
public static int getY(Action action) {
return action.y;
}
}
And Reader for Client. This should be the last class you need to run the client.
package com.game.loader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import com.connection.Client;
import com.game.Frame;
import com.game.menu.GameMenu;
public class Reader {
public static String ReadCache(String string) {
int CurrentLine = 0;
String returnement = "";
try {
BufferedReader Reader = new BufferedReader(new FileReader(new File(string)));
for(String line = Reader.readLine(); line != null; line = Reader.readLine()){
if(CurrentLine == 0){
returnement = line;
}
CurrentLine++;
}
} catch (FileNotFoundException e) {
new File(Frame.drive +"//FM_Cache").mkdirs();
return "WeHadToMakeNewFile";
} catch (IOException e) {
e.printStackTrace();
}
return returnement;
}
public static String UpdateCache(String path) {
String[] pieces = path.split("/");
String returnement = "skip";
System.out.println(Frame.drive + "//FM_Cache/" + path);
if(new File(Frame.drive +"//FM_Cache/" +path).exists()){
returnement = (Frame.drive +"//FM_Cache/" +path);
}
else{ //If file doesen't exit we make one and parent folders.
File file = new File(Frame.drive +"//FM_Cache/" +path);
file.getParentFile().mkdirs();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
returnement = (Frame.drive +"//FM_Cache/" +path);
}
return returnement;
}
}
Runnable server:
package com.server;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.apache.commons.io.IOUtils;
import com.connection.Action;
import com.connection.Incomingdata;
import com.connection.LoadCache;
import com.game.loader.Reader;
import com.game.player.Player;
public class Server {
//Every connection got their own unique id
private static int uniqueId;
//List all the clients
private static ArrayList<ClientThread> al;
private static boolean running = false;
#SuppressWarnings("unused")
private SimpleDateFormat sdf;
final Path base = Paths.get("Data", "Cache");
public Server(int port) {
sdf = new SimpleDateFormat("HH:mm:ss");
al = new ArrayList<ClientThread>();
}
public void start() {
running = true;
try {
//Server socket
ServerSocket serverSocket = new ServerSocket(Screen.portnumber);
System.out.println("Server is running and waiting for Clients to connect.");
while(running){
Socket socket = serverSocket.accept();
if(!running){ //this will make server running stop.
System.out.println("Closing the server..");
break;
}
ClientThread t = new ClientThread(socket);
al.add(t); //saving new client to our arraylist.
t.run();
}
try{
serverSocket.close();
for(int i = 0; i< al.size(); i++){//We forget about all the clients.
//Maybe also save all the data here?
ClientThread tc = al.get(i);
try{
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE){}
}
} catch(Exception e){e.printStackTrace();}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void close() {
running = false;
try {
new Socket("localhost", Screen.portnumber);
} catch (Exception e) { System.out.println("Can't disconnect.."); }
}
synchronized void remove(int id) {
// scan the array list until we find the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
public static boolean isRunning(){
return running;
}
class ClientThread extends Thread {
//The socket where to listen/talk
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
BufferedInputStream buffIn;
//my unique id (easier for deconnection)
int id;
//Objects that we will be receiving
Incomingdata datain;
//the date we connect
String date;
Player player;
boolean Connected = false;
//Constructor
ClientThread(Socket socket){
id = uniqueId++;
this.socket = socket;
try{
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
} catch (Exception e){
System.out.println("Couldn't create Input/Output streams");
}
date = new Date().toString();
}
// what will run forever
public void run() {
// to loop until LOGOUT
Connected = true;
while(Connected) {
try {
datain = (Incomingdata) sInput.readObject();
}
catch (IOException e) {
System.out.println("Exception reading Streams: " + e);
break;
}
catch(ClassNotFoundException e2) {
break;
}
if(!Incomingdata.getUsername(datain).isEmpty()){
switch(Action.getType(Incomingdata.getAction(datain))) { //CHANGE!!
case 0://Log in/off
System.out.println(Incomingdata.getUsername(datain) +", " +Incomingdata.getPassword(datain) + " trying to connect.");
if(Player.getPassword(Reader.ReadPlayerData("Data/Players/" +Incomingdata.getUsername(datain) +".txt")) == Incomingdata.getPassword(datain)){
player = Reader.ReadPlayerData("Data/Players/" +Incomingdata.getUsername(datain) +".txt");
System.out.println(Player.getUsername(player) +"Just connected!");
Player.isOnline(player);
}
break;
case 1://Talk
System.out.println(Incomingdata.getUsername(datain) + ": " +Action.getString(Incomingdata.getAction(datain)));
break;
case 2://Move
break;
}
}
else if(Action.getString(Incomingdata.getAction(datain)) != null){
File[] Data = Reader.getFiles(Action.getString(Incomingdata.getAction(datain)));
LoadCache LoadedCache[] = new LoadCache[Data.length];
for(int i = 0; i<Data.length; i++){
Path filePath = Paths.get(Data[i].getPath());
Path relativePath = base.relativize(filePath); //= filePath - base (so to say)
LoadedCache[i] = new LoadCache(relativePath.toString(), Data[i].length());
}
System.out.println(LoadedCache.length);
try {
sOutput.writeObject(LoadedCache);
sOutput.flush();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for(File file : Data){
try {
if(file.isFile()){
byte[] bytearray = new byte[(int) file.length()];
buffIn = new BufferedInputStream(new FileInputStream(file));
buffIn.read(bytearray, 0, bytearray.length);
sOutput.write(bytearray, 0, bytearray.length);
sOutput.flush();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
buffIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Cache updated!");
}
}
// remove myself from the arrayList containing the list of the
System.out.println(Player.getUsername(player) +", " +Player.getPassword(player) +" disconnected.");
remove(id);
close();
}
// try to close everything
private void close() {
// try to close the connection
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
}
}
Reader.java for server:
package com.game.loader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import org.apache.commons.io.filefilter.FileFileFilter;
import com.game.player.CharacterClass;
import com.game.player.Equipment;
import com.game.player.Friends;
import com.game.player.Inventory;
import com.game.player.Orbs;
import com.game.player.Player;
import com.game.player.Quest;
import com.game.world.Tile;
public class Reader {
public static Player temporary;
static int stage = 0;
private static int count = 0;
private static int totalfolders = 0;
private static File[] files = new File[NumberOfFiles("Data/Cache/")];
public static Player ReadPlayerData(String string) {
Player player = null;
int CurrentLine = 0;
String[] All = new String[100]; //This may need to be extended.
try {
BufferedReader Reader = new BufferedReader(new FileReader(new File(string)));
for(String line = Reader.readLine(); line != null; line = Reader.readLine()){
All[CurrentLine] = line;
CurrentLine++;
}
} catch (FileNotFoundException e) {
System.out.println("Someone is trying to log in using wrong username.");
} catch (IOException e) {
e.printStackTrace();
}
player = new Player(string, All[0], new Tile(Integer.parseInt(All[1].split(", ")[0]), Integer.parseInt(All[1].split(", ")[1]), Integer.parseInt(All[1].split(", ")[2])),
Integer.parseInt(All[2]), Integer.parseInt(All[3]), Integer.parseInt(All[4]), new CharacterClass(All[5]), new Orbs(All[6].split(", ")), null, new Inventory(All[8].split(", ")),
null, new Equipment(All[10].split(", ")), new Friends(All[11].split(", ")), /* All[12] = guild,*/ Integer.parseInt(All[13]), true, false, null, null, Integer.parseInt(All[18]), /*All[19] = StartDate,*/ All[20]);
temporary = player;
return player;
}
public static boolean CacheReader(String string) {
File[] all = new File(string).listFiles(); //We list all the files from path
int folders = 0;
for(int i = 0; i < all.length; i++){
if(!all[i].isDirectory()) { //folders are not added to this list. :)
System.out.println("((i = " +i +") - (folders = " +folders +")) + (stage = " +stage +") = " +(i-folders+stage));
files[i-folders+stage] = all[i];
}
else{
folders++;
totalfolders++;
}
}
stage += all.length-folders; //We add number of files from every directory to stage.
for(int i = 0; i < all.length; i++){ //Then we seek for all the sub-directories
if(all[i].isDirectory()){
CacheReader(all[i].getPath()); //and add all the files from sub-directories to out file list
}
}
return true;
}
public static File[] getFiles(String string) {
if(string == "New"){
}
return files;
}
public static int NumberOfFiles(String string) {
File[] filenames;
filenames = new File(string).listFiles();
count += filenames.length; //We add all the files from the File(string) Note!: Also folders
for(int i = 0; i < filenames.length; i++){
if(filenames[i].isDirectory()){
NumberOfFiles(filenames[i].getPath());
count--;
}
}
return count;
}
}
Umm.. I think you can remove everything related to player, since it's not part of cache update system.. also there are some unused imports in those, I didn't remove all of them. Most of TextArea.Addline();s I changed to System.out.println(); if you find one, you can aswell replace it with System.out.println(); or if you don't need it you can remove it. What ever.. I just would like to find an answer..
try to write the byte array to the ObjectOutputStream as an object:
final byte[] bytearray = new byte[(int) file.length()];
buffIn = new BufferedInputStream(new FileInputStream(file));
buffIn.read(bytearray, 0, bytearray.length);
sOutput.writeObject(bytearray);
And to read it as an Object:
final BufferedOutputStream Bos =
new BufferedOutputStream(new FileOutputStream(result));
byte[] mybytearray = (byte[])sInput.readObject();
Bos.write(mybytearray, 0, BytesRead);
I hope it helps.
Don't use multiple streams to read from the same socket, or write to it either. Use the object streams for everything.
Your copy loops are incorrect, because they aren't loops. You can't assume that read() fills the buffer. The canonical stream copy loop in Java is like so:
int count;
byte[] buffer = new byte[8192]; // or more, code works with any size >= 1
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
I have written a java code to transfer files from one server to another using the concept of socket programming. I got the codes from another java forum that meet my requirements. The program is said to transfer large sized files (like .mkv , .mprg movies) from one machine to another and can be used to transfer files of all formats. But after running the codes I found that the program is not able to transfer large sized files such as movies and even pdf of sizes 80mb or 111mb. The program has used bytebuffer but still error occurs. The codes are as follows (I got them from this site http://www.coderpanda.com/java-socket-programming-transferring-large-sized-files-through-socket/)
ClientMain.java
import java.io.IOException;
import java.net.Socket;
public class ClientMain
{
private DirectoryTxr transmitter = null;
Socket clientSocket = null;
private boolean connectedStatus = false;
private String ipAddress;
String srcPath = null;
String dstPath = "";
public ClientMain()
{
}
public void setIpAddress(String ip)
{
this.ipAddress = ip;
}
public void setSrcPath(String path)
{
this.srcPath = path;
}
public void setDstPath(String path)
{
this.dstPath = path;
}
private void createConnection()
{
Runnable connectRunnable = new Runnable()
{
public void run()
{
while (!connectedStatus)
{
try
{
clientSocket = new Socket(ipAddress, 22);
connectedStatus = true;
transmitter = new DirectoryTxr(clientSocket, srcPath, dstPath);
}
catch (IOException io)
{
io.printStackTrace();
}
}
}
};
Thread connectionThread = new Thread(connectRunnable);
connectionThread.start();
}
public static void main(String[] args)
{
ClientMain main = new ClientMain();
main.setIpAddress("localHost");
main.setSrcPath("C:/Transfer/");
main.setDstPath("C:/Receive");
main.createConnection();
}
}
DirectoryTxr.java
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class DirectoryTxr
{
Socket clientSocket = null;
String srcDir = null;
String dstDir = null;
byte[] readBuffer = new byte[1024];
private InputStream inStream = null;
private OutputStream outStream = null;
int state = 0;
final int permissionReqState = 1;
final int initialState = 0;
final int dirHeaderSendState = 2;
final int fileHeaderSendState = 3;
final int fileSendState = 4;
final int fileFinishedState = 5;
private boolean isLive = false;
private int numFiles = 0;
private int filePointer = 0;
String request = "May I send?";
String respServer = "Yes,You can";
String dirResponse = "Directory created...Please send files";
String fileHeaderRecvd = "File header received ...Send File";
String fileReceived = "File Received";
String dirFailedResponse = "Failed";
File[] opFileList = null;
public DirectoryTxr(Socket clientSocket, String srcDir, String dstDir)
{
try
{
this.clientSocket = clientSocket;
inStream = clientSocket.getInputStream();
outStream = clientSocket.getOutputStream();
isLive = true;
this.srcDir = srcDir;
this.dstDir = dstDir;
state = initialState;
readResponse();
sendMessage(request);
state = permissionReqState;
}
catch (IOException io)
{
io.printStackTrace();
}
}
private void sendMessage(String message)
{
try
{
sendBytes(request.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
private void readResponse()
{
Runnable readRunnable = new Runnable()
{
public void run()
{
while (isLive)
{
try
{
int num = inStream.read(readBuffer);
if (num > 0)
{
byte[] tempArray = new byte[num];
System.arraycopy(readBuffer, 0, tempArray, 0, num);
processBytes(tempArray);
}
}
catch (SocketException se)
{
System.exit(0);
}
catch (IOException io)
{
io.printStackTrace();
isLive = false;
}
}
}
};
Thread readThread = new Thread(readRunnable);
readThread.start();
}
private void sendDirectoryHeader()
{
File file = new File(srcDir);
if (file.isDirectory())
{
try
{
String[] childFiles = file.list();
numFiles = childFiles.length;
String dirHeader = "$" + dstDir + "#" + numFiles + "&";
sendBytes(dirHeader.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException en)
{
en.printStackTrace();
}
}
else
{
System.out.println(srcDir + " is not a valid directory");
}
}
private void sendFile(String dirName)
{
File file = new File(dirName);
if (!file.isDirectory())
{
try
{
int len = (int) file.length();
int buffSize = len / 8;
RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel channel = raf.getChannel();
int numRead = 0;
while (numRead >= 0)
{
ByteBuffer buf = ByteBuffer.allocate(1024 * 100000);
numRead = channel.read(buf);
if (numRead > 0)
{
byte[] array = new byte[numRead];
System.arraycopy(buf.array(), 0, array, 0, numRead);
sendBytes(array);
}
}
System.out.println("Finished");
}
catch (IOException io)
{
io.printStackTrace();
}
}
}
private void sendHeader(String fileName)
{
try
{
File file = new File(fileName);
if (file.isDirectory())
return;
String header = "&" + fileName + "#" + file.length() + "*";
sendHeader(header);
sendBytes(header.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
private void sendBytes(byte[] dataBytes)
{
synchronized (clientSocket)
{
if (outStream != null)
{
try
{
outStream.write(dataBytes);
outStream.flush();
}
catch (IOException io)
{
io.printStackTrace();
}
}
}
}
private void processBytes(byte[] data)
{
try
{
String parsedMessage = new String(data, "UTF-8");
System.out.println(parsedMessage);
setResponse(parsedMessage);
}
catch (UnsupportedEncodingException u)
{
u.printStackTrace();
}
}
private void setResponse(String message)
{
if (message.trim().equalsIgnoreCase(respServer) && state == permissionReqState)
{
state = dirHeaderSendState;
sendDirectoryHeader();
}
else if (message.trim().equalsIgnoreCase(dirResponse) && state == dirHeaderSendState)
{
state = fileHeaderSendState;
if (LocateDirectory())
{
createAndSendHeader();
}
else
{
System.out.println("Vacant or invalid directory");
}
}
else if (message.trim().equalsIgnoreCase(fileHeaderRecvd) && state == fileHeaderSendState)
{
state = fileSendState;
sendFile(opFileList[filePointer].toString());
state = fileFinishedState;
filePointer++;
}
else if (message.trim().equalsIgnoreCase(fileReceived) && state == fileFinishedState)
{
if (filePointer < numFiles)
{
createAndSendHeader();
}
System.out.println("Successfully sent");
}
else if (message.trim().equalsIgnoreCase(dirFailedResponse))
{
System.out.println("Going to exit....Error ");
}
else if (message.trim().equalsIgnoreCase("Thanks"))
{
System.out.println("All files were copied");
}
}
private void closeSocket()
{
try
{
clientSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
private boolean LocateDirectory()
{
boolean status = false;
File file = new File(srcDir);
if (file.isDirectory())
{
opFileList = file.listFiles();
numFiles = opFileList.length;
if (numFiles <= 0)
{
System.out.println("No files found");
}
else
{
status = true;
}
}
return status;
}
private void createAndSendHeader()
{
File opFile = opFileList[filePointer];
String header = "&" + opFile.getName() + "#" + opFile.length() + "*";
try
{
state = fileHeaderSendState;
sendBytes(header.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e)
{
}
}
private void sendListFiles()
{
createAndSendHeader();
}
}
ServerMain.java
public class ServerMain {
public ServerMain() {
}
public static void main(String[] args) {
DirectoryRcr dirRcr = new DirectoryRcr();
}
}
DirectoryRcr.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class DirectoryRcr
{
String request = "May I send?";
String respServer = "Yes,You can";
String dirResponse = "Directory created...Please send files";
String dirFailedResponse = "Failed";
String fileHeaderRecvd = "File header received ...Send File";
String fileReceived = "File Received";
Socket socket = null;
OutputStream ioStream = null;
InputStream inStream = null;
boolean isLive = false;
int state = 0;
final int initialState = 0;
final int dirHeaderWait = 1;
final int dirWaitState = 2;
final int fileHeaderWaitState = 3;
final int fileContentWaitState = 4;
final int fileReceiveState = 5;
final int fileReceivedState = 6;
final int finalState = 7;
byte[] readBuffer = new byte[1024 * 100000];
long fileSize = 0;
String dir = "";
FileOutputStream foStream = null;
int fileCount = 0;
File dstFile = null;
public DirectoryRcr()
{
acceptConnection();
}
private void acceptConnection()
{
try
{
ServerSocket server = new ServerSocket(22);
socket = server.accept();
isLive = true;
ioStream = socket.getOutputStream();
inStream = socket.getInputStream();
state = initialState;
startReadThread();
}
catch (IOException io)
{
io.printStackTrace();
}
}
private void startReadThread()
{
Thread readRunnable = new Thread()
{
public void run()
{
while (isLive)
{
try
{
int num = inStream.read(readBuffer);
if (num > 0)
{
byte[] tempArray = new byte[num];
System.arraycopy(readBuffer, 0, tempArray, 0, num);
processBytes(tempArray);
}
sleep(100);
} catch (SocketException s)
{
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException i)
{
i.printStackTrace();
}
}
}
};
Thread readThread = new Thread(readRunnable);
readThread.start();
}
private void processBytes(byte[] buff) throws InterruptedException
{
if (state == fileReceiveState || state == fileContentWaitState)
{
if (state == fileContentWaitState)
state = fileReceiveState;
fileSize = fileSize - buff.length;
writeToFile(buff);
if (fileSize == 0)
{
state = fileReceivedState;
try
{
foStream.close();
}
catch (IOException io)
{
io.printStackTrace();
}
System.out.println("Received " + dstFile.getName());
sendResponse(fileReceived);
fileCount--;
if (fileCount != 0)
{
state = fileHeaderWaitState;
}
else
{
System.out.println("Finished");
state = finalState;
sendResponse("Thanks");
Thread.sleep(2000);
System.exit(0);
}
System.out.println("Received");
}
}
else
{
parseToUTF(buff);
}
}
private void parseToUTF(byte[] data)
{
try
{
String parsedMessage = new String(data, "UTF-8");
System.out.println(parsedMessage);
setResponse(parsedMessage);
}
catch (UnsupportedEncodingException u) {
u.printStackTrace();
}
}
private void setResponse(String message)
{
if (message.trim().equalsIgnoreCase(request) && state == initialState)
{
sendResponse(respServer);
state = dirHeaderWait;
}
else if (state == dirHeaderWait)
{
if (createDirectory(message))
{
sendResponse(dirResponse);
state = fileHeaderWaitState;
}
else
{
sendResponse(dirFailedResponse);
System.out.println("Error occurred...Going to exit");
System.exit(0);
}
} else if (state == fileHeaderWaitState)
{
createFile(message);
state = fileContentWaitState;
sendResponse(fileHeaderRecvd);
}
else if (message.trim().equalsIgnoreCase(dirFailedResponse))
{
System.out.println("Error occurred ....");
System.exit(0);
}
}
private void sendResponse(String resp)
{
try
{
sendBytes(resp.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
private boolean createDirectory(String dirName)
{
boolean status = false;
dir = dirName.substring(dirName.indexOf("$") + 1, dirName.indexOf("#"));
fileCount = Integer.parseInt(dirName.substring(dirName.indexOf("#") + 1, dirName.indexOf("&")));
if (new File(dir).mkdir())
{
status = true;
System.out.println("Successfully created directory " + dirName);
}
else if (new File(dir).mkdirs())
{
status = true;
System.out.println("Directories were created " + dirName);
}
else if (new File(dir).exists())
{
status = true;
System.out.println("Directory exists" + dirName);
}
else
{
System.out.println("Could not create directory " + dirName);
status = false;
}
return status;
}
private void createFile(String fileName)
{
String file = fileName.substring(fileName.indexOf("&") + 1, fileName.indexOf("#"));
String lengthFile = fileName.substring(fileName.indexOf("#") + 1, fileName.indexOf("*"));
fileSize = Integer.parseInt(lengthFile);
dstFile = new File(dir + "/" + file);
try
{
foStream = new FileOutputStream(dstFile);
System.out.println("Starting to receive " + dstFile.getName());
}
catch (FileNotFoundException fn)
{
fn.printStackTrace();
}
}
private void writeToFile(byte[] buff)
{
try
{
foStream.write(buff);
}
catch (IOException io)
{
io.printStackTrace();
}
}
private void sendBytes(byte[] dataBytes)
{
synchronized (socket)
{
if (ioStream != null)
{
try
{
ioStream.write(dataBytes);
}
catch (IOException io)
{
io.printStackTrace();
}
}
}
}
}
Note that:-
ClientMain.java and DirectoryTxr.java are the two classes under client application.
ServerMain.java and DirectoryRcr.java are the two classes under Server application.
run the ClientMain.java and ServerMain.java simultaneously
Also specify the source directory, destination directory and host address of the machine in which server is running in the ClientMain.java(as per your computer). Here we are not specifying source file ,instead a source directory or folder is specifying.So the entire files of source directory will be transferred.
I would really appreciate if someone can help me with the problem.
You can check this code. This code can send files till 2GB of file size. Checked and working. Basically what I do here is first I send the file size and file name in an object then I start sending the file. First of all let me show you the class whose object will carry the File's details and send it to Receiver.
FileTransfer Class:
public class FileDetails implements Serializable {
String name;
long size;
public void setDetails(String name, long size) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public long getSize() {
return size;
}
}
Sender:
ServerSocket sendServer = null;
Socket sendSocket;
FileDetails details;
byte data[];
try {
File file = new File("File Url");
// Getting file name and size
if (file.length() > Integer.MAX_VALUE) {
System.out.println("File size exceeds 2 GB");
} else {
sendServer = new ServerSocket(5050);
System.out.println("Waiting for Client...");
sendSocket = sendServer.accept();
// File Object for accesing file Details
System.out.println("Connected to Client...");
data = new byte[2048]; // Here you can increase the size also which will send it faster
details = new FileDetails();
details.setDetails(file.getName(), file.length());
// Sending file details to the client
System.out.println("Sending file details...");
ObjectOutputStream sendDetails = new ObjectOutputStream(sendSocket.getOutputStream());
sendDetails.writeObject(details);
sendDetails.flush();
// Sending File Data
System.out.println("Sending file data...");
FileInputStream fileStream = new FileInputStream(file);
BufferedInputStream fileBuffer = new BufferedInputStream(fileStream);
OutputStream out = sendSocket.getOutputStream();
int count;
while ((count = fileBuffer.read(data)) > 0) {
System.out.println("Data Sent : " + count);
out.write(data, 0, count);
out.flush();
}
out.close();
fileBuffer.close();
fileStream.close();
}
} catch (Exception e) {
System.out.println("Error : " + e.toString());
}
Receiver's code :
int port = 5050;
try {
System.out.println("Connecting to Server...");
Socket receiveSocket = new Socket("IP of Server", port);
System.out.println("Connected to Server...");
// Getting file details
System.out.println("Getting details from Server...");
ObjectInputStream getDetails = new ObjectInputStream(receiveSocket.getInputStream());
FileDetails details = (FileDetails) getDetails.readObject();
System.out.println("Now receiving file...");
// Storing file name and sizes
String fileName = details.getName();
System.out.println("File Name : " + fileName);
byte data[] = new byte[2048]; // Here you can increase the size also which will receive it faster
FileOutputStream fileOut = new FileOutputStream("D:\\" + fileName);
InputStream fileIn = receiveSocket.getInputStream();
BufferedOutputStream fileBuffer = new BufferedOutputStream(fileOut);
int count;
int sum = 0;
while ((count = fileIn.read(data)) > 0) {
sum += count;
fileBuffer.write(data, 0, count);
System.out.println("Data received : " + sum);
fileBuffer.flush();
}
System.out.println("File Received...");
fileBuffer.close();
fileIn.close();
} catch (Exception e) {
System.out.println("Error : " + e.toString());
}
Hope this helps you.
You don't need all this. The canonical way to copy a stream in Java is as follows. It works for any buffer size greater than zero. I generally use 8192. There is certainly no necessity to read entire files into memory. It just wastes time and space.
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
If you know the size in advance and need to keep the socket open for another transfer:
while (total < length && (count = in.read(buffer, 0, length-total > buffer.length ? buffer.length : (int)(length-total))) > 0)
{
out.write(buffer, 0, count);
total += count;
}
where total is a long initialized to zero before this loop, and length is the length you know in advance.
I am new to Java, and learning new things everyday. English is not my mother language, I'm sorry.
So, I'm making a maze game in Java to learn while writing code.
For my maze game, the player needs to get to the exit of the maze asap. And the time he has, needs to be saved in an encrypted text file.
So I've got a package Highscores combining several classes. The code works more or less, it outputs in the console. Now what I need is that that output gets outputted on a JPanel next to my maze. I've added some extra info in the code
Here is my highscore class:
public class Highscore {
// An arraylist of the type "score" we will use to work with the scores inside the class
private ArrayList<Score> scores;
// The name of the file where the highscores will be saved
private static final String highscorefile = "Resources/scores.dat";
//Initialising an in and outputStream for working with the file
ObjectOutputStream output = null;
ObjectInputStream input = null;
public Highscore() {
//initialising the scores-arraylist
scores = new ArrayList<Score>();
}
public ArrayList<Score> getScores() {
loadScoreFile();
sort();
return scores;
}
private void sort() {
ScoreVergelijken comparator = new ScoreVergelijken();
Collections.sort(scores, comparator);
}
public void addScore(String name, int score) {
loadScoreFile();
scores.add(new Score(name, score));
updateScoreFile();
}
public void loadScoreFile() {
try {
input = new ObjectInputStream(new FileInputStream(highscorefile));
scores = (ArrayList<Score>) input.readObject();
} catch (FileNotFoundException e) {
System.out.println("[Laad] FNF Error: " + e.getMessage());
} catch (IOException e) {
System.out.println("[Laad] IO Error: " + e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println("[Laad] CNF Error: " + e.getMessage());
} finally {
try {
if (output != null) {
output.flush();
output.close();
}
} catch (IOException e) {
System.out.println("[Laad] IO Error: " + e.getMessage());
}
}
}
public void updateScoreFile() {
try {
output = new ObjectOutputStream(new FileOutputStream(highscorefile));
output.writeObject(scores);
} catch (FileNotFoundException e) {
System.out.println("[Update] FNF Error: " + e.getMessage() + ",the program will try and make a new file");
} catch (IOException e) {
System.out.println("[Update] IO Error: " + e.getMessage());
} finally {
try {
if (output != null) {
output.flush();
output.close();
}
} catch (IOException e) {
System.out.println("[Update] Error: " + e.getMessage());
}
}
}
public String getHighscoreString() {
String highscoreString = "";
int max = 10;
ArrayList<Score> scores;
scores = getScores();
int i = 0;
int x = scores.size();
if (x > max) {
x = max;
}
while (i < x) {
highscoreString += (i + 1) + ".\t" + scores.get(i).getNaam() + "\t\t" + scores.get(i).getScore() + "\n";
i++;
}
return highscoreString;
}
}
Here is my Main class:
public class Main {
public static void main(String[] args) {
Highscore hm = new Highscore();
hm.addScore("Bart",240);
hm.addScore("Marge",300);
hm.addScore("Maggie",220);
hm.addScore("Homer",100);
hm.addScore("Lisa",270);
hm.addScore(LabyrinthProject.View.MainMenu.username,290);
System.out.print(hm.getHighscoreString());
} }
Score class :
public class Score implements Serializable {
private int score;
private String naam;
public Score() {
}
public int getScore() {
return score;
}
public String getNaam() {
return naam;
}
public Score(String naam, int score) {
this.score = score;
this.naam = naam;
}
}
ScoreVergelijken class (which means CompareScore)
public class ScoreVergelijken implements Comparator<Score> {
public int compare(Score score1, Score score2) {
int sc1 = score1.getScore();
int sc2 = score2.getScore();
if (sc1 > sc2){
return -1; // -1 means first score is bigger then second score
}else if (sc1 < sc2){
return +1; // +1 means that score is lower
}else{
return 0; // 0 means score is equal
}
} }
If anyone could explain to me what to use, it would be greatly appreciated! Thank you very much!
Also, how to use those highscores and store them encrypted in a text file. How can I achieve that?
Sincerely, A beginner java student.
to keep your data encrypted in a file, you can use CipherIn/OutputStream, just like this
public static void main(String[] args) throws Exception {
// got this example from http://www.java2s.com/Tutorial/Java/0490__Security/UsingCipherInputStream.htm
write();
read();
}
public static void write() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("DES");
kg.init(new SecureRandom());
SecretKey key = kg.generateKey();
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
Class spec = Class.forName("javax.crypto.spec.DESKeySpec");
DESKeySpec ks = (DESKeySpec) skf.getKeySpec(key, spec);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("keyfile"));
oos.writeObject(ks.getKey());
Cipher c = Cipher.getInstance("DES/CFB8/NoPadding");
c.init(Cipher.ENCRYPT_MODE, key);
CipherOutputStream cos = new CipherOutputStream(new FileOutputStream("ciphertext"), c);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(cos));
pw.println("Stand and unfold yourself");
pw.flush();
pw.close();
oos.writeObject(c.getIV());
oos.close();
}
public static void read() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("keyfile"));
DESKeySpec ks = new DESKeySpec((byte[]) ois.readObject());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey key = skf.generateSecret(ks);
Cipher c = Cipher.getInstance("DES/CFB8/NoPadding");
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec((byte[]) ois.readObject()));
CipherInputStream cis = new CipherInputStream(new FileInputStream("ciphertext"), c);
BufferedReader br = new BufferedReader(new InputStreamReader(cis));
System.out.println(br.readLine());
}
Basically you asked two questions and Leo answered your second question.
Your first question is...
what I need is that ...[the high scores]... gets outputted on a JPanel next to my maze
You didn't post any GUI code, but a subclass of JTextComponent would be more appropriate than a JPanel. Simply add a component, for example JTextArea and call its setText() method with your high score string as the method argument.
I'm trying to send and object over udp by first serializing it and then deserializing it on the other end. I thought this would be trivial since I have sent other data over udp before and serialized stuff to the files etc.
I have debugged thing some time now and I keep getting EOFException on the receiving end. Packets arrive properly but somehow deserialization fails. I'm not sure if the mistake is in sender or receiver. I suppose the problem might be about the receiver not knowing the size of the packet.
Here is my sender class:
package com.machinedata.sensordata;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.content.Context;
import android.util.Log;
import com.machinedata.io.DataSerializer;
import com.machinedata.io.ManagerUdpPacket;
/**
* This class sends udp-packets. It is used to send driver's information to the manager tablet.
* #author tuomas
*
*/
public class UdpSender
{
private final int MANAGER_PORT = 1234;
private String ip = "192.168.11.50"; //tablet's IP
private DatagramSocket sock = null;
private InetAddress host;
private String mType;
private DataSerializer dataser;
public UdpSender(Context context)
{
try
{
sock = new DatagramSocket();
host = InetAddress.getByName(ip); //tabletin ip
}
catch(Exception e)
{
System.err.println("Exception alustettaessa senderia" + e);
}
dataser = new DataSerializer(context);
}
/**
* With this function we can send packets about our machine to the manager to
* see in the fleet-view.
*/
public void sendToManager(ManagerUdpPacket managerUdp)
{
//serialize
Log.v("sendudp", "Send a packet: " + managerUdp.getDriver());
//serialize
byte[] data = dataser.serializeManagerPacket(managerUdp);
//send
try
{
DatagramPacket dp = new DatagramPacket(data , data.length , host , MANAGER_PORT);
sock.send(dp);
}
catch(IOException e)
{
System.err.println("IOException senderissa " + e);
}
}
public void close()
{
sock.close();
}
}
Here is the serialization function:
/**
* Serializes packet to be sent over udp to the manager tablet.
*/
public byte[] serializeManagerPacket(ManagerUdpPacket mp)
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(mp);
oos.close();
// get the byte array of the object
byte[] obj= baos.toByteArray();
baos.close();
return obj;
}
catch(Exception e) {
e.printStackTrace();
}
return null;
}
Packet receiver class
public class UdpReceiver {
private DatagramSocket clientSocket;
private byte[] receiveData;
private final int timeout = 1;
/**
* Create a receiver.
* #param port Port to receive from.
* #param signCount Number of signals in a packet
*/
public UdpReceiver(int port)
{
//receiveData = serializeManagerPacket(new ManagerUdpPacket("asd", new MachineData(1, 2, "asd", "modelName"), 1,2,3,4,5.0,null));
try{
clientSocket=new DatagramSocket(port);
clientSocket.setReceiveBufferSize(2048);
clientSocket.setSoTimeout(timeout);
}catch(SocketException e){
Log.e("ERR", "SocketException in UdpReceiver()");
}
}
public void close()
{
clientSocket.close();
}
/**
* Receive a data packet and split it into array.
* #param data Array to put data in, must be correct size
* #return True on successful read, false otherwise
*/
public ManagerUdpPacket receive()
{
//receive a packet
DatagramPacket recvPacket = new DatagramPacket(receiveData, receiveData.length);
try{
clientSocket.receive(recvPacket);
}catch(IOException e){
Log.e("ERR", "IOException in UdpReceiver.receive");
return null;
}
ManagerUdpPacket obj = deserializeManagerPacket(receiveData);
if (obj != null)
Log.v("udpPacket", "UDP saatu: " + obj.getDriver());
return obj;
}
/**
* Deserialize the udp-packet back to readable data.
* #param data
* #return
*/
public ManagerUdpPacket deserializeManagerPacket(byte[] data)
{
try
{
ObjectInputStream iStream = new ObjectInputStream(new ByteArrayInputStream(data));
ManagerUdpPacket obj = (ManagerUdpPacket) iStream.readObject();
iStream.close();
return obj;
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
}
Thread which listens packets in receiving end:
dataStreamTask = new TimerTask()
{
public void run()
{
if (currentlyStreaming)
{
ManagerUdpPacket mp = udpReceiver.receive();
if(mp != null)
{
Log.v("log", "Paketti saatu! " + mp.getDriver());
}
//stop thread until next query
try {
synchronized(this){
this.wait(queryInterval);
}
} catch (InterruptedException e) {
Log.e("ERR", "InterruptedException in TimerTask.run");
}
}
}
And finally the class I'm sending over the UDP:
public class ManagerUdpPacket implements Serializable
{
private static final long serialVersionUID = 9169314425496496555L;
private Location gpsLocation;
private double totalFuelConsumption;
private long operationTime;
//workload distribution
private long idleTime = 0;
private long normalTime = 0;
private long fullTime = 0;
private int currentTaskId;
private String driverName;
String machineModelName = "";
String machineName = "";
int machineIconId = -1;
int machinePort = -1;
public ManagerUdpPacket(String driver, MachineData machine, int currentTaskId, long idleTime, long fullTime, long operationTime, double fuelConsumption, Location location)
{
driverName = driver;
this.currentTaskId = currentTaskId;
this.idleTime = idleTime;
this.fullTime = fullTime;
this.operationTime = operationTime;
this.totalFuelConsumption = fuelConsumption;
this.gpsLocation = location;
machineModelName = machine.getModelName();
machineName = machine.getName();
machineIconId = machine.getIconId();
machinePort = machine.getPort();
}
public String getDriver()
{
return driverName;
}
public int getCurrentTaskId()
{
return currentTaskId;
}
public long getIdleTime()
{
return idleTime;
}
public long getFullTime()
{
return fullTime;
}
public long getOperationTime()
{
return operationTime;
}
public double getTotalFuelConsumption()
{
return totalFuelConsumption;
}
public double getLocation()
{
return gpsLocation.getLatitude();
}
public String getMachineModelName()
{
return machineModelName;
}
public String getMachineName()
{
return machineName;
}
public int getMachineIconId()
{
return machineIconId;
}
public int getMachinePort()
{
return machinePort;
}
}
I tried to get the packet size from the size of the serialized packet or inserting arbitrary 2048 based on some examples on internet. Couldn't get it work though.
As far as i know the receive function returns the length of the bytes it received. But your buffer will be full:
Example:
int buffersize = 1024;
You send 8bytes over udp.
So your byte[] will be full with your 8 bytes but the rest of the 1024 will be 0.
save the size you get by the .receive() call and just save all values of your buffer to another byte[] and you should get your object.
For your example:
public ManagerUdpPacket receive()
{
int receivedBytes = 0;
//receive a packet
DatagramPacket recvPacket = new DatagramPacket(receiveData, receiveData.length);
try{
receivedBytes = clientSocket.receive(recvPacket);
}catch(IOException e){
Log.e("ERR", "IOException in UdpReceiver.receive");
return null;
}
byte[] myObject = new byte[receivedBytes];
for(int i = 0; i < receivedBytes; i++)
{
myObject[i] = receiveData[i];
}
ManagerUdpPacket obj = deserializeManagerPacket(myObject);
if (obj != null)
Log.v("udpPacket", "UDP saatu: " + obj.getDriver());
return obj;
}
When receiving data on UDP, always use java.net.DatagramSocket.getReceiveBufferSize();. This is the actual size of the platform or SP_RCVBUF for the socket. Since UDP is a datagram based protocol unlike TCP, which is streaming protocol, receiving buffers become critical for data sanity. Usually, receiving and sending buffers are equal in size, but you are not bothered while sending when using DatagramSocket.send(DatagramPacket), alternately, you can also use DatagramSocket.setSendBufferSize(DatagramSocket.getSendBufferSize()) for using the SO_SNDBUF option for this socket. Keep in mind, in UDP, if you use a SO_SNDBUF size greater than platform's, the packet can be discarded.
I'm making a multiplayer game in java, and I'm really have some issues here. For some reason, my Datagram socket will stop receiving packets set from the client even though according to the console, it recieved them perfectly fine before. I don't know much about networking or programming with sockets, so this has me stumped.
Here's my code:
Server:
package server;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import shared.BaseEntity;
import shared.MethodNotOverridenException;
import shared.Packet;
import shared.Player;
public class S_GameLoop implements Runnable{
//Constants
private static final int TICKS_PER_SECOND = 25;
private static final int TICKS_TO_SKIP = 1000 / TICKS_PER_SECOND;
private static final int MAX_FRAMESKIP = 5;
private static final int SPAWN_COORD_X = 50;
private static final int SPAWN_COORD_Y = 50;
private Vector<S_Client> ClientList;
private Map<Integer, BaseEntity> EntityMap;
private AtomicInteger IDGenerator;
private boolean gameIsRunning = true;
private DatagramSocket socket;
byte[] recieveData = new byte[1024];
byte[] prevRecieveData = new byte[1024];
private int port;
private int loops;
public S_GameLoop(int port) {
ClientList = new Vector<S_Client>();
this.port = port;
IDGenerator = new AtomicInteger();
EntityMap = new HashMap<Integer, BaseEntity>();
}
private void Init() throws SocketException {
System.out.println("INIT");
socket = new DatagramSocket(port);
System.out.println("[Server] Create listen server on " + socket.getLocalAddress().getHostAddress() + " on port " + socket.getLocalPort());
socket.setSoTimeout(0);
}
private void Running() {
System.out.println("S_GameLoop staring");
long nextGameTick = System.currentTimeMillis();
DatagramPacket recievePacket = new DatagramPacket(recieveData, recieveData.length);
//GameLoop goes here
while(gameIsRunning) {
loops = 0;
//Receive the data
try {
socket.receive(recievePacket);
} catch (IOException e1) {
e1.printStackTrace();
}
while(System.currentTimeMillis() > nextGameTick && loops < MAX_FRAMESKIP) {
try {
Update(recievePacket);
} catch (MethodNotOverridenException | IOException e) {
System.err.println(e);
}
nextGameTick += TICKS_TO_SKIP;
loops++;
}
nextGameTick += TICKS_TO_SKIP;
loops++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void Update(DatagramPacket recievePacket) throws IOException, MethodNotOverridenException {
if(prevRecieveData != recieveData) {
parseData(formatData(recievePacket.getData()), recievePacket);
prevRecieveData = recieveData;
} else {
return;
}
}
public static Packet formatData(byte[] data) {
try {
if(data[1] == 0);
String tag = new String(Arrays.copyOfRange(data, 1, 8));
System.out.println("[Server] Recieved packet " + data[0] + " " + new String(tag));
return new Packet(data[0],tag.getBytes(), Arrays.copyOfRange(data, 8, data.length));
} catch (ArrayIndexOutOfBoundsException e) {
return new Packet((byte)0, new byte[0], new byte[0]);
}
}
private void parseData(Packet p, DatagramPacket recievePacket) throws IOException, MethodNotOverridenException {
if(p.getTag() == new byte[0]) {
System.out.println("[Server] Recieved NULL packet");
return;
}
switch (p.getTagAsString()) {
case "LGN_RQS": System.out.println("[Server] Login Request Recieved");
//Login was accepted
//Create a Client ref, and add it to the vector
S_Client newClient = new S_Client(recievePacket.getAddress(), recievePacket.getPort());
ClientList.add(newClient);
//Create a player and add it to Entity list
Player newPlayer = new Player(IDGenerator.getAndIncrement(), ClientList.indexOf(newClient));
EntityMap.put(newPlayer.getEntID(), newPlayer);
System.out.println("[Server] Created new Player with EID " + newPlayer.getEntID() + " and CID " + newPlayer.getCID());
//Send reply to Client that is logging in
sendData(new Packet((byte)2, "LGN_ACP".getBytes(), ("CID;" + ClientList.indexOf(newClient) + ";EID;" + newPlayer.getEntID()).getBytes()).getBytes(), newClient.getIp(), newClient.getPort());
//New Entity was created
//sendData(newPlayer.onCreate(this));
break;
case "HND_SHK": System.out.println("[Server] Handshake Recieved");
String fdata = new String(p.getData());
String[] data = fdata.split(";");
//Get client by client ID
S_Client c = ClientList.get(Integer.parseInt(data[1]));
c.setUsername(data[3]);
System.out.println("[Server] Set Client " + data[1] + "'s username to " + data[3]);
//Now spawn the player
sendData(new Packet((byte)9, "PLR_SPW".getBytes(), ("CID;" + data[1] + ";X;" + SPAWN_COORD_X + ";Y;" + SPAWN_COORD_Y).getBytes()).getBytes());
break;
}
}
public String[] byteArrayToStringArray(byte[] b) {
String fdata = new String(b);
return fdata.split(";");
}
public void createEntity(BaseEntity be) throws MethodNotOverridenException, IOException {
int ID = IDGenerator.incrementAndGet();
be.setEntID(ID);
EntityMap.put(ID, be);
sendData(be.onCreate(this));
}
public void sendData(byte[] sendData, InetAddress IP, int port) throws IOException {
System.out.println("[Server] Send packet " + sendData[0] + " " + new String(Arrays.copyOfRange(sendData, 1, 8)));
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IP, port);
socket.send(sendPacket);
}
public void sendData(byte[] sendData) throws IOException {
for (S_Client entry : ClientList) {
sendData(sendData, entry.getIp(), entry.getPort());
}
}
#Override
public void run() {
try {
Init();
Running();
} catch (SocketException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
}
}
Client:
package client;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Arrays;
import java.util.Vector;
import shared.BaseEntity;
import shared.Packet;
import shared.Player;
public class C_GameLoop {
//How fast should the game update?
private static final int TICKS_PER_SECOND = 25;
//How many ticks should be skipped in order to run it at that speed?
//If it runs faster, then the Render() will be called more often
private static final int TICKS_TO_SKIP = 1000 / TICKS_PER_SECOND;
//How many times should you skip rendering, if you have to?
private static final int MAX_FRAMESKIP = 5;
RenderCanvas rc;
InetAddress ServerIP;
private DatagramSocket socket;
private int port;
private boolean connectedToServer = false;
private boolean waitForData = false;
private String username = "Dummy";
byte[] sendPacket;
Vector<BaseEntity> RenderList;
Player player;
int fps = 0;
public C_GameLoop(RenderCanvas rc){
this.rc = rc;
RenderList = new Vector<BaseEntity>();
}
public boolean Connect(InetAddress ServerIP, int port) throws IOException {
this.port = port;
this.ServerIP = ServerIP;
socket = new DatagramSocket();
socket.setSoTimeout(4000);
DatagramPacket recieveData = new DatagramPacket(new byte[1024], new byte[1024].length);
System.out.println("[Client] Connecting to: " + ServerIP.getHostAddress() + ":" + port);
//Send a login request
sendData(new Packet((byte)1, "LGN_RQS".getBytes()).getBytes());
int retries = 0;
//Start the connect loop
while(!connectedToServer) {
try {
socket.receive(recieveData);
waitForData = false;
parseData(formatData(recieveData.getData()));
//recieveData.setData(new Packet((byte)0, new byte[0], new byte[0]).getBytes());
} catch (SocketTimeoutException e) {
if(waitForData = true && retries <= 4) {
System.out.println("[Client] Failed to recieve response from server, retrying");
parseData(formatData(recieveData.getData()));
retries++;
} else {
System.out.println("[Client] Failed to Connect to the server!");
return false;
}
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
public void sendData(byte[] data) throws IOException {
System.out.println("[Client] Sent packet " + data[0] + " " + new String(Arrays.copyOfRange(data, 1, 8)));
DatagramPacket sendPacket = new DatagramPacket(data, data.length, ServerIP, port);
socket.send(sendPacket);
waitForData = true;
}
private void parseData(Packet p) throws IOException {
switch (p.getTagAsString()) {
case "LGN_ACP": System.out.println("[Client] Login Accepted");
//Get the data needed to create a new player from the packet
String fdata = new String(p.getData());
String[] data = fdata.split(";");
Player player = new Player(Integer.parseInt(data[1]), Integer.parseInt(data[3].trim()));
//Add it to the render list
this.player = player;
rc.getCamera().addDrawableEntity(player);
System.out.println("[Client] Player created with CID " + data[1] + " and EID " + data[3]);
//Send the handshake
System.out.println("[Client] Finshing Handshake...");
sendData(new Packet((byte)4, "HND_SHK".getBytes(), ("CID;" + player.getCID() + ";Username;" + username).getBytes()).getBytes());
break;
case "PLR_SPW": System.out.println("[Client] Spawn Recieved");
//Get the coords
String[] spawn_data = byteArrayToStringArray(p.getData());
this.player.setX(Integer.parseInt(spawn_data[3]));
this.player.setY(Integer.parseInt(spawn_data[5].trim()));
sendData(new Packet((byte)0, "KEP_ALV".getBytes()).getBytes());
break;
}
}
public String[] byteArrayToStringArray(byte[] b) {
String fdata = new String(b);
return fdata.split(";");
}
/*
* Formats data into a packet
*/
public static Packet formatData(byte[] data) {
try {
if(data[1] == 0);
String tag = new String(Arrays.copyOfRange(data, 1, 8));
System.out.println("[Client] Recieved packet " + data[0] + " " + new String(tag));
return new Packet(data[0],tag.getBytes(), Arrays.copyOfRange(data, 8, data.length));
} catch (ArrayIndexOutOfBoundsException e) {
return new Packet((byte)0, new byte[0], new byte[0]);
}
}
}
Console output when running code:
INIT
[Server] Create listen server on 0.0.0.0 on port 4334
S_GameLoop staring
[Client] Connecting to: 127.0.0.1:4334
[Client] Sent packet 1 LGN_RQS
[Server] Recieved packet 1 LGN_RQS
[Server] Login Request Recieved
[Server] Created new Player with EID 0 and CID 0
[Server] Send packet 2 LGN_ACP
[Client] Recieved packet 2 LGN_ACP
[Client] Login Accepted
[Client] Player created with CID 0 and EID 0
[Client] Finshing Handshake...
[Client] Sent packet 4 HND_SHK
[Client] Failed to recieve response from server, retrying
(Same lines as previous 6 just repeat 4 times)
[Client] Failed to Connect to the server!
Any Ideas?
It looks like your Server class is designed to be used as the Runnable of some worker thread.
I suspect that the problem is that the run() method is dying due to an uncaught exception, and that the worker thread is simply terminating.
I recommend that you configure a default uncaught exception handler to (at least) log the stack trace for the fatal exception. Refer to the Thread javadocs for details.