简体   繁体   English

Java通过套接字发送和接收文件(字节[])

[英]Java sending and receiving file (byte[]) over sockets

I am trying to develop a very simple client / server where the client converts a file to bytes, sends it to the server, and then converts the bytes back in to a file.我正在尝试开发一个非常简单的客户端/服务器,其中客户端将文件转换为字节,将其发送到服务器,然后将字节转换回文件。

Currently the program just creates an empty file.目前该程序只创建一个空文件。 I'm not a fantastic Java developer so any help much appreciated.我不是一个出色的 Java 开发人员,因此非常感谢任何帮助。

This is the server part that receives what the client sends.这是接收客户端发送的内容的服务器部分。

ServerSocket serverSocket = null;

    serverSocket = new ServerSocket(4444);


    Socket socket = null;
    socket = serverSocket.accept();

    DataOutputStream out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    byte[] bytes = new byte[1024];

    in.read(bytes);
    System.out.println(bytes);

    FileOutputStream fos = new FileOutputStream("C:\\test2.xml");
    fos.write(bytes);

And here is the client part这是客户端部分

Socket socket = null;
    DataOutputStream out = null;
    DataInputStream in = null;
    String host = "127.0.0.1";     

    socket = new Socket(host, 4444);
    out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

    File file = new File("C:\\test.xml");
    //InputStream is = new FileInputStream(file);
    // Get the size of the file
    long length = file.length();
    if (length > Integer.MAX_VALUE) {
        System.out.println("File is too large.");
    }
    byte[] bytes = new byte[(int) length];

    //out.write(bytes);
    System.out.println(bytes);

    out.close();
    in.close();
    socket.close();

The correct way to copy a stream in Java is as follows:在 Java 中复制流的正确方法如下:

int count;
byte[] buffer = new byte[8192]; // or 4096, or more
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

Wish I had a dollar for every time I've posted that in a forum.希望每次我在论坛上发帖时都能得到一美元。

Thanks for the help.谢谢您的帮助。 I've managed to get it working now so thought I would post so that the others can use to help them.我现在已经设法让它工作了,所以我想我会发布以便其他人可以用来帮助他们。

Server:服务器:

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;

        try {
            serverSocket = new ServerSocket(4444);
        } catch (IOException ex) {
            System.out.println("Can't setup server on this port number. ");
        }

        Socket socket = null;
        InputStream in = null;
        OutputStream out = null;
        
        try {
            socket = serverSocket.accept();
        } catch (IOException ex) {
            System.out.println("Can't accept client connection. ");
        }
        
        try {
            in = socket.getInputStream();
        } catch (IOException ex) {
            System.out.println("Can't get socket input stream. ");
        }

        try {
            out = new FileOutputStream("M:\\test2.xml");
        } catch (FileNotFoundException ex) {
            System.out.println("File not found. ");
        }

        byte[] bytes = new byte[16*1024];

        int count;
        while ((count = in.read(bytes)) > 0) {
            out.write(bytes, 0, count);
        }

        out.close();
        in.close();
        socket.close();
        serverSocket.close();
    }
}

and the Client:和客户:

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = null;
        String host = "127.0.0.1";

        socket = new Socket(host, 4444);
        
        File file = new File("M:\\test.xml");
        // Get the size of the file
        long length = file.length();
        byte[] bytes = new byte[16 * 1024];
        InputStream in = new FileInputStream(file);
        OutputStream out = socket.getOutputStream();
        
        int count;
        while ((count = in.read(bytes)) > 0) {
            out.write(bytes, 0, count);
        }

        out.close();
        in.close();
        socket.close();
    }
}

Here is the server Open a stream to the file and send it overnetwork这是服务器打开文件流并通过网络发送

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleFileServer {

  public final static int SOCKET_PORT = 5501;
  public final static String FILE_TO_SEND = "file.txt";

  public static void main (String [] args ) throws IOException {
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    OutputStream os = null;
    ServerSocket servsock = null;
    Socket sock = null;
    try {
      servsock = new ServerSocket(SOCKET_PORT);
      while (true) {
        System.out.println("Waiting...");
        try {
          sock = servsock.accept();
          System.out.println("Accepted connection : " + sock);
          // send file
          File myFile = new File (FILE_TO_SEND);
          byte [] mybytearray  = new byte [(int)myFile.length()];
          fis = new FileInputStream(myFile);
          bis = new BufferedInputStream(fis);
          bis.read(mybytearray,0,mybytearray.length);
          os = sock.getOutputStream();
          System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
          os.write(mybytearray,0,mybytearray.length);
          os.flush();
          System.out.println("Done.");
        } catch (IOException ex) {
          System.out.println(ex.getMessage()+": An Inbound Connection Was Not Resolved");
        }
        }finally {
          if (bis != null) bis.close();
          if (os != null) os.close();
          if (sock!=null) sock.close();
        }
      }
    }
    finally {
      if (servsock != null)
        servsock.close();
    }
  }
}

Here is the client Recive the file being sent overnetwork这是客户端接收通过网络发送的文件

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class SimpleFileClient {

  public final static int SOCKET_PORT = 5501;
  public final static String SERVER = "127.0.0.1";
  public final static String
       FILE_TO_RECEIVED = "file-rec.txt";

  public final static int FILE_SIZE = Integer.MAX_VALUE;

  public static void main (String [] args ) throws IOException {
    int bytesRead;
    int current = 0;
    FileOutputStream fos = null;
    BufferedOutputStream bos = null;
    Socket sock = null;
    try {
      sock = new Socket(SERVER, SOCKET_PORT);
      System.out.println("Connecting...");

      // receive file
      byte [] mybytearray  = new byte [FILE_SIZE];
      InputStream is = sock.getInputStream();
      fos = new FileOutputStream(FILE_TO_RECEIVED);
      bos = new BufferedOutputStream(fos);
      bytesRead = is.read(mybytearray,0,mybytearray.length);
      current = bytesRead;

      do {
         bytesRead =
            is.read(mybytearray, current, (mybytearray.length-current));
         if(bytesRead >= 0) current += bytesRead;
      } while(bytesRead > -1);

      bos.write(mybytearray, 0 , current);
      bos.flush();
      System.out.println("File " + FILE_TO_RECEIVED
          + " downloaded (" + current + " bytes read)");
    }
    finally {
      if (fos != null) fos.close();
      if (bos != null) bos.close();
      if (sock != null) sock.close();
    }
  }    
}

To avoid the limitation of the file size , which can cause the Exception java.lang.OutOfMemoryError to be thrown when creating an array of the file size byte[] bytes = new byte[(int) length];避免文件大小的限制,在创建文件大小byte[] bytes = new byte[(int) length];的数组时,会导致抛出异常java.lang.OutOfMemoryError byte[] bytes = new byte[(int) length]; , instead we could do ,相反我们可以做

    byte[] bytearray = new byte[1024*16];
    FileInputStream fis = null;
    try {

        fis = new FileInputStream(file);
        OutputStream output= socket.getOututStream();
        BufferedInputStream bis = new BufferedInputStream(fis);

        int readLength = -1;
        while ((readLength = bis.read(bytearray)) > 0) {
            output.write(bytearray, 0, readLength);

        }
        bis.close();
        output.close();
    }
    catch(Exception ex ){

        ex.printStackTrace();
    } //Excuse the poor exception handling...

Rookie, if you want to write a file to server by socket, how about using fileoutputstream instead of dataoutputstream?菜鸟,如果想通过socket写文件到服务器,用fileoutputstream代替dataoutputstream怎么样? dataoutputstream is more fit for protocol-level read-write. dataoutputstream 更适合协议级读写。 it is not very reasonable for your code in bytes reading and writing.以字节为单位的代码读写不是很合理。 loop to read and write is necessary in java io. java io中需要循环读写。 and also, you use a buffer way.而且,您使用缓冲方式。 flush is necessary.冲洗是必要的。 here is a code sample: http://www.rgagnon.com/javadetails/java-0542.html这是一个代码示例: http : //www.rgagnon.com/javadetails/java-0542.html

Adding up on EJP's answer;加上 EJP 的回答; use this for more fluidity.使用它以获得更多的流动性。 Make sure you don't put his code inside a bigger try catch with more code between the .read and the catch block, it may return an exception and jump all the way to the outer catch block, safest bet is to place EJPS's while loop inside a try catch, and then continue the code after it, like:确保你没有把他的代码放在一个更大的 try catch 中,在 .read 和 catch 块之间有更多的代码,它可能会返回一个异常并一直跳到外部的 catch 块,最安全的做法是放置 EJPS 的 while 循环在 try catch 中,然后在它之后继续代码,例如:

int count;
byte[] bytes = new byte[4096];
try {
    while ((count = is.read(bytes)) > 0) {
        System.out.println(count);
        bos.write(bytes, 0, count);
    }
} catch ( Exception e )
{
    //It will land here....
}
// Then continue from here

EDIT: ^This happened to me cuz I didn't realize you need to put socket.shutDownOutput() if it's a client-to-server stream!编辑:^这发生在我身上,因为我没有意识到如果它是客户端到服务器的流,你需要放置 socket.shutDownOutput() !

Hope this post solves any of your issues希望这篇文章能解决你的任何问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM