【问题标题】:Java file not working when sent over a network通过网络发送 Java 文件时不起作用
【发布时间】:2015-04-25 13:38:38
【问题描述】:

所以我正在为 java 实现客户端和套接字。我想通过套接字在 tcp 上发送大文件,我也能够发送文件,但唯一的问题是另一端的文件不完整或不工作。我已经检查了正在传输的位,那么错误是什么。

客户端:

   Socket sock = new Socket("127.0.0.1", 1056);
    byte[] mybytearray = new byte[1024];
    InputStream is = sock.getInputStream();
    FileOutputStream fos = new FileOutputStream("abc.mp3");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    int bytesRead = is.read(mybytearray, 0, mybytearray.length);
    int len = 0;
    while((len = is.read(mybytearray)) != -1)
    {
    bos.write(mybytearray, 0, len);
    System.out.println("sending");
    }
  
    bos.close();
    sock.close();

服务器端:

  ServerSocket ss = new ServerSocket(1056);
    while (true) {
      Socket s = ss.accept();
      PrintStream out = new PrintStream(s.getOutputStream());
      BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
      String info = null;
      String request = null;
      System.out.println("sending");      
    	  String filename = "abc.mp3";
        File fi = new File(filename);
        InputStream fs = new FileInputStream(fi);
        int n = fs.available();
        byte buf[] = new byte[1024];
        out.println("Content_Length:" + n);
        out.println("");
        while ((n = fs.read(buf)) >= 0) {
          out.write(buf, 0, n);
             System.out.println("sending");
        }
        out.close();
        s.close();
        in.close();
		
		}

【问题讨论】:

  • 这里有更好的问题 exp hello,所以我正在为 java 实现客户端和套接字。我想使用 TCP 发送大文件。我能够发送文件,但文件不完整或不工作。正在传输位,那么错误是什么。它适用于小型 txt 文件。

标签: java tcp client mp3 server


【解决方案1】:

当您通过 TCP 连接时,您会创建一个可以读取和写入的网络流,类似于您使用的所有其他流。将大量数据写入流不是一个好主意,因此我建议您将选定的文件分成较小的数据包,其中每个数据包长度为 1024 字节(1KB),然后将所有数据包发送到服务器。 SendTCP 函数如下:(我使用了 Windows 窗体来使事情更明显)

public void SendTCP(string M, string IPA, Int32 PortN)
{
    byte[] SendingBuffer = null
    TcpClient client = null;
    lblStatus.Text = "";
    NetworkStream netstream = null;
    try
    {
         client = new TcpClient(IPA, PortN);
         lblStatus.Text = "Connected to the Server...\n";
         netstream = client.GetStream();
         FileStream Fs = new FileStream(M, FileMode.Open, FileAccess.Read);
         int NoOfPackets = Convert.ToInt32
      (Math.Ceiling(Convert.ToDouble(Fs.Length) / Convert.ToDouble(BufferSize)));
         progressBar1.Maximum = NoOfPackets;
         int TotalLength = (int)Fs.Length, CurrentPacketLength, counter = 0;
         for (int i = 0; i < NoOfPackets; i++)
         {
             if (TotalLength > BufferSize)
             {
                 CurrentPacketLength = BufferSize;
                 TotalLength = TotalLength - CurrentPacketLength;
             }
             else
                 CurrentPacketLength = TotalLength;
                 SendingBuffer = new byte[CurrentPacketLength];
                 Fs.Read(SendingBuffer, 0, CurrentPacketLength);
                 netstream.Write(SendingBuffer, 0, (int)SendingBuffer.Length);
                 if (progressBar1.Value >= progressBar1.Maximum)
                      progressBar1.Value = progressBar1.Minimum;
                 progressBar1.PerformStep();
             }

             lblStatus.Text=lblStatus.Text+"Sent "+Fs.Length.ToString()+" 
                        bytes to the server";
             Fs.Close();
         }
    catch (Exception ex)
    {
         Console.WriteLine(ex.Message);
    }
    finally
    {
         netstream.Close();
         client.Close();
    }
} 

如您所见,正在构建 TCP 客户端和网络流,并启动网络连接。根据 1024 字节的缓冲区大小打开所选文件后,计算将要发送的数据包数。还有另外两个变量 CurrentPacketLength 和 TotalLength。如果所选文件的总长度大于缓冲区大小,则将 CurrentPacketLength 设置为缓冲区大小,否则为什么要发送一些空字节,因此将 CurrentPacketLength 设置为文件的总长度。之后,我从总长度中减去当前,所以实际上我们可以说总长度表示尚未发送的数据总量。剩下的就很简单了,从文件流中读取数据并根据 CurrentPacketLength 将其写入 SendingBuffer 并将缓冲区写入网络流。

服务器端,应用程序正在侦听传入连接:

public void ReceiveTCP(int portN)
{
    TcpListener Listener = null;
    try
    {
        Listener = new TcpListener(IPAddress.Any, portN);
        Listener.Start();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    byte[] RecData = new byte[BufferSize];
    int RecBytes;

    for (; ; )
    {
        TcpClient client = null;
        NetworkStream netstream = null;
        Status = string.Empty;
        try
        {                          
             string message = "Accept the Incoming File ";
             string caption = "Incoming Connection";
             MessageBoxButtons buttons = MessageBoxButtons.YesNo;
             DialogResult result;

             if (Listener.Pending())
             {
                  client = Listener.AcceptTcpClient();
                  netstream = client.GetStream();
                  Status = "Connected to a client\n";
                  result = MessageBox.Show(message, caption, buttons);

                  if (result == System.Windows.Forms.DialogResult.Yes)
                  {
                       string SaveFileName=string.Empty;
                       SaveFileDialog DialogSave = new SaveFileDialog();
                       DialogSave.Filter = "All files (*.*)|*.*";
                       DialogSave.RestoreDirectory = true;
                       DialogSave.Title = "Where do you want to save the file?";
                       DialogSave.InitialDirectory = @"C:/";
                       if (DialogSave.ShowDialog() == DialogResult.OK)
                            SaveFileName = DialogSave.FileName;
                       if (SaveFileName != string.Empty)
                       {
                           int totalrecbytes = 0;
                           FileStream Fs = new FileStream
            (SaveFileName, FileMode.OpenOrCreate, FileAccess.Write);
                           while ((RecBytes = netstream.Read
                (RecData, 0, RecData.Length)) > 0)
                           {
                                Fs.Write(RecData, 0, RecBytes);
                                totalrecbytes += RecBytes;
                           }
                           Fs.Close();
                       }
                       netstream.Close();
                       client.Close();
                  }
             }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            //netstream.Close();
        }
    }
}

创建了一个 TCP 侦听器并开始侦听指定的端口。缓冲区大小再次设置为 1024 字节。 TCP 侦听器可以在调用 AcceptTcpClient 方法之前预先检查是否有任何连接挂起。如果有任何挂起的连接,则返回 true。这种方法是避免套接字被阻塞的好方法。在从网络流中读取任何内容之前,会出现一个消息框询问您是否要接受传入的连接,然后会打开一个 SaveFileDialog,当您输入文件名和扩展名时,将构建一个文件流并开始读取网络流和写入文件流。在您的代码中创建一个线程并在创建的线程中运行接收方法。我已经使用该应用程序在 LAN 中发送了超过 100 MB 的文件。

更多详情,请查看article

【讨论】:

  • "向流中写入大量数据不是一个好主意。"错误的。错误的。错误的。您应该尽可能多地写入块,并检查写入字节数的结果,以防系统无法全部接受。编写较小的块(如 1KiB)意味着您可能会发送 1KiB 的数据包,该数据包小于最大数据包大小并且在网络上的效率较低。
  • @BrianWhite 请不要以封面来判断一本书。阅读整个答案,然后你可以做任何你想做的事情,比如否决我的答案。
【解决方案2】:

所以,首先你要这样做

int bytesRead = is.read(mybytearray, 0, mybytearray.length);

最多可将 1024 个字节读入 mybytearray。

你什么也没做,我不明白你为什么要这样做。您永远不会写入这些字节,因此如果 while 循环读取任何内容,它们就会被覆盖。 把那个删掉就行了。 while 循环应该涵盖所有这些。

【讨论】:

  • did 不起作用,之后我什至无法发送文本文件。不过谢谢
猜你喜欢
  • 1970-01-01
  • 2015-06-23
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 2015-02-19
  • 2022-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多