通过Java Socket发送多个文件

huangapple go评论68阅读模式
英文:

Sending Multiple Files Over a Java Socket

问题

我正试图让一个程序运行起来,其中客户端将同一个文件发送到服务器100次,然后检查以确保所有100个文件与原始文件相同。目前我无法让它正常工作,因为服务器从客户端读取了一些随机数量的字节,这导致一些文件中的字节数过多,我不确定如何继续。目前它可以正确地发送所有100个文件,但有些文件里面的内容太多了。

客户端代码:

String sentence;
InetAddress host = InetAddress.getLocalHost();
Socket clientSocket = new Socket(host, 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

long startTime, endTime, tGap, totalTime;
byte[] sendData;
int filesSent = 0;

File fs = new File("Test1.txt");

int fileLength = (int) fs.length();
totalTime = 0;

while (filesSent < 100) {
    FileInputStream fin = new FileInputStream(fs);
    int numBytes = 0;
    System.out.println("Sending file to server...");
    sendData = new byte[1024];
    if (fileLength < 1024) {
        numBytes = fin.read(sendData, 0, fileLength);
    } else {
        numBytes = fin.read(sendData, 0, 1024);
    }

    startTime = System.currentTimeMillis();
    int count = 0;
    while (numBytes != -1) {
        count += numBytes;
        System.out.println(numBytes);
        sentence = new String(sendData);
        outToServer.writeBytes(sentence);
        numBytes = fin.read(sendData, 0, 1024);
    }
    System.out.println(count);
    endTime = System.currentTimeMillis();
    tGap = endTime - startTime;
    totalTime = totalTime + tGap;
    System.out.println("Finished run " + filesSent + " with a time of " + tGap);
    filesSent++;
    fin.close();
    outToServer.flush();
}
clientSocket.close();

System.out.println("I am done to send " + filesSent + " times file, and the average time is: " + (double) totalTime / filesSent);
}

服务器代码:

String clientSentence;
int filesRecieved = 0;
ServerSocket welcomeSocket = new ServerSocket(6789);
int numError = 0;
int numBytes;
char check = 'a';
System.out.println("I am starting now....");

long startTime, endTime, tGap, totalTime;
totalTime = 0;

Socket connectionSocket;
connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));

while (filesRecieved < 100) {
    FileOutputStream outPut = new FileOutputStream("receivedFile" + filesRecieved + ".txt");
    char[] receiveData = new char[1024];
    numBytes = inFromClient.read(receiveData, 0, 1024);
    while (numBytes != 1024) {
        numBytes += inFromClient.read(receiveData, 0, 1024 - numBytes);
    }
    System.out.println("OG Bytes:" + numBytes);
    startTime = System.currentTimeMillis();

    int count = 0;
    while (numBytes != -1 && count < 105942) {
        try {
            count += numBytes;
            clientSentence = new String(receiveData, 0, numBytes);
            outPut.write(clientSentence.getBytes(), 0, numBytes);
            System.out.println(numBytes);
            numBytes = inFromClient.read(receiveData, 0, 1024);
            System.out.println(count);
        } catch (Exception e) {
            break;
        }
    }
    outPut.close();
    endTime = System.currentTimeMillis();
    tGap = endTime - startTime;
    totalTime = totalTime + tGap;
    System.out.println("I have received" + "receivedFile" + filesRecieved + ".txt using time = " + tGap);
    filesRecieved++;
}

connectionSocket.close();

System.out.println("I am done now..." + "and the average time used to receive each copy is: " + totalTime / filesRecieved);
welcomeSocket.close();
英文:

I am trying to get a program working where a client sends the same file to the server 100 times and then checks to make sure all 100 files are the same as the original. Right now I cant get it to work because the server reads some arbitrary amount of bytes from the client and it causes some files to have too many bytes in them and I'm not sure how to proceed. Right now it will send all 100 files properly but some files just have too much stuff in them.

Client code

String sentence;
InetAddress host = InetAddress.getLocalHost();
Socket clientSocket = new Socket(host, 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
long startTime, endTime, tGap, totalTime;
byte[] sendData;
int filesSent = 0;
File fs = new File(&quot;Test1.txt&quot;);
int fileLength = (int) fs.length();
totalTime = 0;
while (filesSent &lt; 100) {
FileInputStream fin = new FileInputStream(fs);
int numBytes = 0;
System.out.println(&quot;Sending file to server...&quot;);
sendData = new byte[1024];
if (fileLength &lt; 1024) {
numBytes = fin.read(sendData, 0, fileLength);
} else {
numBytes = fin.read(sendData, 0, 1024);
}
startTime = System.currentTimeMillis();
int count = 0;
while (numBytes != -1) {
count += numBytes;
System.out.println(numBytes);
sentence = new String(sendData);
outToServer.writeBytes(sentence);
numBytes = fin.read(sendData, 0, 1024);
}
System.out.println(count);
endTime = System.currentTimeMillis();
tGap = endTime - startTime;
totalTime = totalTime + tGap;
System.out.println(&quot;Finished run &quot; + filesSent + &quot; with a time of &quot; + tGap);
filesSent++;
fin.close();
outToServer.flush();
}
clientSocket.close();
System.out.println(&quot;I am done to send &quot; + filesSent + &quot; times file, and the average time is: &quot; + (double) totalTime / filesSent);
}

Server Code

String clientSentence;
int filesRecieved = 0;
ServerSocket welcomeSocket = new ServerSocket(6789);
int numError = 0;
int numBytes;
char check = &#39;a&#39;;
System.out.println(&quot;I am starting now....&quot;);
long startTime, endTime, tGap, totalTime;
totalTime = 0;
Socket connectionSocket;
connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
while(filesRecieved &lt; 100) {
FileOutputStream outPut = new FileOutputStream(&quot;receivedFile&quot; + filesRecieved + &quot;.txt&quot;);
char[] receiveData = new char[1024];
numBytes = inFromClient.read(receiveData, 0, 1024);
while(numBytes != 1024){
numBytes += inFromClient.read(receiveData,0,1024-numBytes);
}
System.out.println(&quot;OG Bytes:&quot; + numBytes);
startTime = System.currentTimeMillis();
int count = 0;
while (numBytes != -1 &amp;&amp; count &lt; 105942) {
try {
count += numBytes;
clientSentence = new String(receiveData, 0, numBytes);
outPut.write(clientSentence.getBytes(), 0, numBytes);
System.out.println(numBytes);
numBytes = inFromClient.read(receiveData, 0, 1024);
System.out.println(count);
}catch(Exception e){
break;
}
}
outPut.close();
endTime = System.currentTimeMillis();
tGap = endTime - startTime;
totalTime = totalTime + tGap;
System.out.println(&quot;I have received&quot; + &quot;receivedFile&quot; + filesRecieved + &quot;.txt using time = &quot; + tGap);
filesRecieved++;
}
connectionSocket.close();
System.out.println(&quot;I am done now...&quot; + &quot;and the average time used to receive each copy is: &quot; + totalTime / filesRecieved);
welcomeSocket.close();

答案1

得分: 2

TCP是一个字节流协议。它没有消息的概念。因此,您需要以一种方式对文件数据进行分帧,以便接收方知道一个文件在哪里结束,下一个文件从哪里开始。在这种情况下,您需要在发送文件数据之前发送文件大小,以便接收方知道每个文件应该期望多少字节。

此外,您没有正确关注每次调用read()时实际读取的字节数。虽然您提供了一个大缓冲区,但不能保证整个缓冲区都会被填满。特别是在文件末尾。

而且不要使用字符串来传输二进制文件数据!

尝试更像这样的方式:

客户端:

File fs = new File("Test1.txt");
long fileLength = fs.length();

InetAddress host = InetAddress.getLocalHost();
Socket clientSocket = new Socket(host, 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

long startTime, endTime, tGap, totalTime = 0;
byte[] sendData = new byte[1024];
int numBytes, filesSent = 0;

while (filesSent < 100) {
    FileInputStream fin = new FileInputStream(fs);
    long thisFileLength = fileLength;

    System.out.println("Sending file to server...");
    startTime = System.currentTimeMillis();

    outToServer.writeLong(thisFileLength);

    while (thisFileLength > 0) {
        if (thisFileLength < sendData.length) {
            numBytes = fin.read(sendData, 0, (int) thisFileLength);
        } else {
            numBytes = fin.read(sendData, 0, sendData.length);
        }

        System.out.println(numBytes);
        if (numBytes < 1) {
            break;
        }

        outToServer.write(sendData, 0, numBytes);
        thisFileLength -= numBytes;
    }

    outToServer.flush();

    endTime = System.currentTimeMillis();
    tGap = endTime - startTime;
    totalTime = totalTime + tGap;
    System.out.println("Finished run " + filesSent + " with a time of " + tGap);
    filesSent++;

    fin.close();

    if (thisFileLength > 0) {
        break;
    }
}

clientSocket.close();

System.out.println("I am done to send " + filesSent + " times file, and the average time is: " + (double) totalTime / filesSent);

服务器:

ServerSocket welcomeSocket = new ServerSocket(6789);
System.out.println("I am starting now....");

Socket connectionSocket;
connectionSocket = welcomeSocket.accept();
DataInputStream inFromClient = new DataInputStream(new BufferedInputStream(connectionSocket.getInputStream()));

long startTime, endTime, tGap, totalTime = 0;
byte[] receiveData = new byte[1024];
int numBytes, filesRecieved = 0;

while (filesRecieved < 100) {
    String filename = "receivedFile" + filesRecieved + ".txt";
    FileOutputStream outPut = new FileOutputStream(filename);

    startTime = System.currentTimeMillis();

    long fileLength = inFromClient.readLong();
    System.out.println("OG Bytes: " + fileLength);

    while (fileLength > 0) {
        if (fileLength < receiveData.length) {
            numBytes = inFromClient.read(receiveData, 0, (int) fileLength);
        } else {
            numBytes = inFromClient.read(receiveData, 0, receiveData.length);
        }

        if (numBytes < 1) {
            break;
        }

        try {
            outPut.write(receiveData, 0, numBytes);
            System.out.println(numBytes);
        } catch (Exception e) {
            break;
        }

        fileLength -= numBytes;
    }

    outPut.close();

    endTime = System.currentTimeMillis();
    tGap = endTime - startTime;
    totalTime = totalTime + tGap;
    System.out.println("I have received " + filename + " using time = " + tGap);
    filesRecieved++;

    if (fileLength > 0) {
        break;
    }
}

connectionSocket.close();

System.out.println("I am done now... and the average time used to receive each copy is: " + totalTime / filesRecieved);
welcomeSocket.close();
英文:

TCP is a byte stream. It has no concept of messages. As such, you need to frame the file data in such a way that the receiver knows where one file ends and the next begins. In this case, you need to send the file size before sending the file data, so the receiver knows how many bytes to expect per file.

Also, you are not paying attention properly to the number of bytes that read() tells you were actually read each time you call it. You are giving it a large buffer, but there is no guarantee that the entire buffer will be filled up. Especially at the end of a file.

And don't transfer binary file data using strings!

Try something more like this instead:

Client:

File fs = new File(&quot;Test1.txt&quot;);
long fileLength = fs.length();

InetAddress host = InetAddress.getLocalHost();
Socket clientSocket = new Socket(host, 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

long startTime, endTime, tGap, totalTime = 0;
byte[] sendData = new byte[1024];
int numBytes, filesSent = 0;

while (filesSent &lt; 100) {
	FileInputStream fin = new FileInputStream(fs);
	long thisFileLength = fileLength;

	System.out.println(&quot;Sending file to server...&quot;);
	startTime = System.currentTimeMillis();

	outToServer.writeLong(thisFileLength);

	while (thisFileLength &gt; 0) {
		if (thisFileLength &lt; sendData.length) {
			numBytes = fin.read(sendData, 0, (int) thisFileLength);
		} else {
			numBytes = fin.read(sendData, 0, sendData.length);
		}

		System.out.println(numBytes);
		if (numBytes &lt; 1) {
			break;
		}

		outToServer.write(sendData, 0, numBytes);
		thisFileLength -= numBytes;
	}

	outToServer.flush();

	endTime = System.currentTimeMillis();
	tGap = endTime - startTime;
	totalTime = totalTime + tGap;
	System.out.println(&quot;Finished run &quot; + filesSent + &quot; with a time of &quot; + tGap);
	filesSent++;

	fin.close();

	if (thisFileLength &gt; 0) {
		break;
	}
}

clientSocket.close();

System.out.println(&quot;I am done to send &quot; + filesSent + &quot; times file, and the average time is: &quot; + (double) totalTime / filesSent);

Server:

ServerSocket welcomeSocket = new ServerSocket(6789);
System.out.println(&quot;I am starting now....&quot;);

Socket connectionSocket;
connectionSocket = welcomeSocket.accept();
DataInputStream inFromClient = new DataInputStream(new BufferedInputStream(connectionSocket.getInputStream()));

long startTime, endTime, tGap, totalTime = 0;
byte[] receiveData = new byte[1024];
int numBytes, filesRecieved = 0;

while (filesRecieved &lt; 100) {
	string filename = &quot;receivedFile&quot; + filesRecieved + &quot;.txt&quot;;
	FileOutputStream outPut = new FileOutputStream(filename);

	startTime = System.currentTimeMillis();

	long fileLength = inFromClient.readLong();
	System.out.println(&quot;OG Bytes: &quot; + fileLength);

	while (fileLength &gt; 0) {
		if (fileLength &lt; receiveData.length) {
			numBytes = inFromClient.read(receiveData, 0, (int) fileLength);
		}
		else {
			numBytes = inFromClient.read(receiveData, 0, receiveData.length);
		}

		if (numBytes &lt; 1) {
			break;
		}

		try {
			outPut.write(receiveData, 0, numBytes);
			System.out.println(numBytes);
		}
		catch (Exception e) {
			break;
		}

		fileLength -= numBytes;
	}

	outPut.close();

	endTime = System.currentTimeMillis();
	tGap = endTime - startTime;
	totalTime = totalTime + tGap;
	System.out.println(&quot;I have received &quot; + filename + &quot; using time = &quot; + tGap);
	filesRecieved++;

	if (fileLength &gt; 0) {
		break;
	}
}

connectionSocket.close();

System.out.println(&quot;I am done now... and the average time used to receive each copy is: &quot; + totalTime / filesRecieved);
welcomeSocket.close();

huangapple
  • 本文由 发表于 2020年9月30日 04:50:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/64127458.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定