所以我正在为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();
}

答案 0 :(得分: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字节。在调用AcceptTcpClient方法之前,TCP侦听器可以预先检查是否有任何挂起的连接。如果有任何挂起的连接,则返回true。此方法是避免套接字被阻止的好方法。在从网络流中读取任何内容之前,会出现一个消息框询问您是否要接受传入连接,然后将打开SaveFileDialog,当您输入文件名加扩展名时,将构建一个文件流并开始从网络流和写入文件流。在代码中创建一个线程,并在创建的线程中运行接收方法。我已经在应用程序的LAN中发送了超过100 MB的文件。
有关详细信息,请查看此article。
答案 1 :(得分:1)
所以,首先你要这样做
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
将最多1024个字节读入mybytearray。
你不做任何事情,我不明白你为什么这样做。你永远不会写那些字节,所以如果while循环读取任何东西它们会被覆盖。 只需删除它。 while循环应涵盖所有这些。