I'm doing a program that sends large files through sockets client-server, that piece of code
while ((bytesRead = in.read(mybytearray, 0, mybytearray.length)) != -1) {
bos.write(mybytearray, 0, bytesRead);
}
All code can be found here
I have already downloaded data as where to pass this number was spooled file? For example there is a file size 35000 bytes transmitted 20000 is broken and how to make the program to start downloading from 20000 bytes to continue?
P.S. I`m very sorry, my English is bad
When you open the connection to the destination file just keep reading it until you reach 20000 bytes, discarding the data.
After you reach your "resume point" start appending the new data to the existing file.
Unfortunately you cannot "seek" a socket the same way you would in something like local file I/O.
Related
I'm sending a string over the socket I previously sent a file to, but the recipient reads it as part of the file itself, is there a way to send a sort of EOF before sending the string?
To send the file I'm using
byte[] buffer = new byte[1024];
int count;
while ((count = fis.read(buffer)) >= 0) os.write(buffer, 0, count);
os.flush();
(and almost the same to receive it)
To send the string I'm using OutputStreamWriter
(Here you are my code: hatebin)
I've also read here that I should send a SOH character, but which one should I send and how?
Thanks in advance.
No there's no way to send an "eof" and then send something afterwards.
If you don't want to open a new connection, there are basically two ways to solve this.
You can modify the client so it recognizes some special byte sequence as a "delimiter", and stops writing to the file when it reads the delimiter from the socket. In this case you need to have some strategy to deal with the possibility that the file actually contains the delimiter.
You can send the size of the file in bytes before sending the file, and modify the client so it counts the number of bytes it reads from the socket. When the client has read enough, it should stop writing to the file.
I have created a basic client-server program that transfers file from server to the client. Since the file is about 500MB, the server transfers the file as chunks of bytes to the client over the DataOutputStream object. While this logic works okay when both client and server are running on the same computer, it doesn't work when the two programs are running on separate computers(Both computers are on the same network and I have disabled the firewall for both)
When running on separate computers the problem is that a few bytes get transferred
Server Logic:
byte byteArr[] = new byte[1024];
while((c=fileInputStream.read(byteArr, 0, 1024) != -1))
{
dataOutputStream.writeBoolean(true);
dataOutputStream.flush();
dataOutputStream.write(byteArr, 0, 1024);
dataOutputStream.flush();
}
/*When running on different computers, after a few hundred iterations
it just stops looping the following lines are never executed*/
dataOutputStream.writeBoolean(false);
System.out.println("Transfer complete");
Client Logic
byte byteArr[] = new byte[1024];
while(dataInputStream.readBoolean())
{
dataInputStream.read(byteArr, 0, 1024);
fileOutputStream.write(byteArr, 0, 1024);
}
A read(buf, 0, 1024) call is not guaranteed to read exactly 1024 bytes. This causes bugs in both pieces of code:
the server incorrectly assumes that each chunk read from the file is always exactly 1024 bytes long and sends the whole buffer to the client.
the client might not read the whole chunk in a single iteration. It will then treat the first byte of the remainder as a boolean and get out of sync with the server.
To resolve this, you could:
send the file size (if known) before sending the file,
then just keep reading until you've read that many bytes.
or send c (the chunk size) instead of a single boolean,
then use dataInputStream.readFully() to make sure that
many bytes will be read.
I'm working on a project which requires transmitting a MP4 video from a Java (Android) server to a C++ (Visual studio) client.
Everything works fine if I use a Java Client, but with the C++ client I receive a file 1 byte larger that the file sent. As a result, the file won't obviously open. I don't know if the problem is just with that extra bit or there is something else wrong.
Here's the relevant code of my C++ Client:
FILE *myFile=std::fopen("scan.mp4","wb");
char *recVideoBuffer=new char[videoSize];//videoSize previously received
int written;
totalBytesRcvd = 0;
while (totalBytesRcvd < videoSize)
{
if ((bytesRcvd = recv(sock, recVideoBuffer, videoSize, 0)) <= 0)
DieWithError("recv() failed or connection closed prematurely");
totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes */
if ((written = fwrite(recVideoBuffer, 1, bytesRcvd, myFile)) != bytesRcvd)
DieWithError("fwrite() failed");
printf("Filesize: %d\nReceived: %d\Written %d\nTotal Received: %d\n\n", videoSize, bytesRcvd, written, totalBytesRcvd);
}
fclose(myFile);
closesocket(sock);
Java Server:
File source = new File (VIDEO_FILE);
byte byteArray[] = new byte [(int)source.length()];
BufferedInputStream bStream = new BufferedInputStream(new FileInputStream(source));
bStream.read(byteArray, 0, byteArray.length);
OutputStream outStream = s.getOutputStream();
outStream.write(byteArray, 0, byteArray.length);
outStream.flush();
outStream.close();
bStream.close();
s.close();
server.close();
Any ideas on what the problem(s) might be and how to fix them?
I've looked around and found some related questions but those were either unanswered or not relevant...
Thanks.
EDIT:
I tried sending a 'abcde' .asc file, and the client receives just 'abcd'. In this case both the files are 5 byte large though.
===
I looked into the byte values of the MP4 files.
The received one has 2 extra bytes, 0a, at the beginning, and is missing the last 2B. Manually changing these values makes the video play correctly.
Where does 0a come from? Obviously because of those 2B the last 2 are not written...
SOLVED
Quite a silly issue really... I would send the video size using println(), which recv() couldn't read entirely, apparently leaving those 0a bytes over the socket, ready to be received by the next recv() along with the file bytes.
That explains why everything worked with the Java client, as I would read the videoSize using readLine() .
How annoying having wasted a day on this, Lol.
I want to write a "simple" Java Server-type application to stream videos to different clients. My first step would be an again "simple" Android App containing a VideoView and a MediaPlayer set to Video Streaming (More Information on Android SDK - MediaPlayer) though later i might add desktop java application too.
What i'm not sure is how i would actually do the streaming on the server. I already wrote a little Http Server processing HTTP GET requests from a client over TCP.
There i write/"stream" the files back using this coding:
FileInputStream fs = new FileInputStream(f);
final byte[] buffer = new byte[1024];
int count = 0;
//add the header information to the respone
while ((count = fs.read(buffer)) >= 0) {
os.write(buffer, 0, count);
}
os.flush();
fs.close();
os.close();
os being the OutputStream of the Response i get through the tcp socket and f being the requested file.
This seems to send the file almost completly at once though and not like i want to, stream it "in chunks".
So my questions are:
What do i, or do i have to change my coding to actually stream the video, or is it already correct this way?
When i want to make it using UDP instead of TCP would i then only put the buffer byte arrays read from the fileinputstream directly into the DatagramPacket and the MediaPlayer would know what to do with it?
PS: I know there are several questions on here about streaming in Java but none of them actually cover the server side but mainly the (in this case Android-) client side.
I am trying to write a server that accepts files and write it in certain directory using DataInputStream and BufferedInputStream.
The server gets 'user name(string)' 'number of files(int)' 'file name(string)' 'size of each file(long)' and 'contents of file which is uninterpreted bytes(byte[])'
and if everything is successful then, I am supposed to send boolean value.
But the problem is that it is not receiving file correctly.
From time to time I get 'broken pipe' error message or the file is corrupted after I receive.
Fixed the problem..
One small thing which may be related to your problem. You should be decrementing your file size variable by the number of bytes actually read, instead of the number of bytes requested to be read:
while(fileSize>0){
if(fileSize < byteSize)
byteSize = (int)fileSize;
int byteRead = din.read(b, 0, byteSize);
fos.write(b);
fileSize -= byteRead; // <-- See here
}
You might be getting this error if when reading the input, the sender closes the connection. It probably has nothing to do with your code. The sender might have timed out, closed the connection before the transfer has finished, or many other things.
Take a look at this related question: How to fix java.net.SocketException: Broken pipe?