2014-11-03 185 views
0

我正在传输不同种类的文件(.png,.txt等)的字节数组。我的套接字开始发送数据,客户端开始接收数据。由于某些原因,.png与服务器端看起来不一样。 (有时它说图像不可读,有时只显示图像的某些部分..等等)?我想知道如何才能让发送的数据实际上与发送的数据相同?任何建议我做错了什么? (注意:如果PNG文件具有Alpha通道,图像似乎总是完全不可读!)数据传输的Java传输字节数组通过套接字损坏的数据

客户端:数据传输的

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

服务器端:

​​

另外!现在,(我不太清楚了,如果我得到这个更早)客户端给我java.util.zip.ZipException: incorrect header check -Exception(并且没有任何文件的压缩是)

东西的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。这应该是您运行客户端所需的最后一个类。

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的服务器:

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();我改为System.out.println();如果你找到一个,你可以用System.out.println()替换它。或者如果你不需要它,你可以删除它。曾经..我只是想什么来寻找答案..

+0

您是否在写入后尝试刷新sOutput(对象流)? – 2014-11-03 21:33:11

+0

我也建议在每一边生成一个校验和并对它们进行比较。 – spudone 2014-11-03 21:50:34

+0

在客户端,您正在混合ObjectOutputStream和底层OutputStream的读取操作。这似乎有点奇怪,因为一个是另一个的包装。在服务器端相同。 – rafalopez79 2014-11-03 21:51:36

回答

-1
  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); 
    } 
    
+0

伟大的建议,但没有解决问题。 :)但是,谢谢你的建议 – user3738243 2014-11-04 12:42:15

+0

你怎么看创建服务器字节阵列使用: 'byte [] bytearray = Files.readAllBytes(file.toPath());' – user3738243 2014-11-05 18:42:09

0

尝试将字节数组写入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); 

我希望它有帮助。

+0

但在server.java我有:“sOutput。写(bytearray,0,bytearray.length);“它与“sOutput.writeObject(bytearray)”不同吗?有什么区别?当然,我可以试试这个,但解释也不错:) – user3738243 2014-11-04 19:45:06

+0

@ user3738243我认为它更容易看到发生了什么,更容易调试它。您发送的字节数组对象在导线的两侧具有相同的内容。 – rafalopez79 2014-11-04 20:37:17

相关问题