Java通过套接字传输字节数组损坏的数据



我正在传输不同类型文件(.png、.txt等)的Byte数组。我的套接字开始发送数据,客户端开始接收数据。出于某种原因,pngs看起来与服务器端不同。(有时它说图像不可读,有时只显示图像的某些部分等)?我想知道我如何才能使发送的数据实际上与发送的数据相同?有什么建议我做错了什么吗?(注意!如果.png文件有alpha通道,图像似乎总是完全无法读取。)

数据传输的客户端:

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();
                        }
                    }

服务器端的数据传输:

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();
                    }

还有!现在(我不太确定我之前是否得到了这个)客户端给了我java.util.zip.ZipException: incorrect header check-异常(并且没有压缩任何文件)

可运行的东西:

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);
    }
}
}

收入数据:

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;
}
}

以及客户读者。这应该是运行客户端所需的最后一个类。

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;
}
}

可运行服务器:

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:

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;
}
}

嗯。。我认为你可以删除所有与播放器相关的内容,因为它不是缓存更新系统的一部分。。还有一些未使用的进口产品,我没有全部删除。TextArea.Addline()的大部分;s我已更改为System.out.println();如果你找到了一个,你也可以用System.out.println()替换它;或者如果你不需要它,你可以把它取下来。。我只是想找到一个答案。。

尝试将字节数组作为对象写入ObjectOutputStream:

 final byte[] bytearray = new byte[(int) file.length()];
 buffIn = new BufferedInputStream(new FileInputStream(file));
 buffIn.read(bytearray, 0, bytearray.length);
 sOutput.writeObject(bytearray);

并将其作为对象读取:

 final BufferedOutputStream Bos = 
    new BufferedOutputStream(new FileOutputStream(result));
 byte[] mybytearray = (byte[])sInput.readObject();
 Bos.write(mybytearray, 0, BytesRead);

我希望它能有所帮助。

  1. 不要使用多个流从同一个套接字进行读取或写入。将对象流用于所有内容。

  2. 您的复制循环不正确,因为它们不是循环。不能假设read()填充了缓冲区。Java中的规范流复制循环是这样的:

    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);
    }
    

最新更新