How to Achieve Transfer File Between Client and Server Using Java Socket

how to achieve transfer file between client and server using java socket

Reading quickly through the source it seems that you're not far off. The following link should help (I did something similar but for FTP). For a file send from server to client, you start off with a file instance and an array of bytes. You then read the File into the byte array and write the byte array to the OutputStream which corresponds with the InputStream on the client's side.

http://www.rgagnon.com/javadetails/java-0542.html

Edit: Here's a working ultra-minimalistic file sender and receiver. Make sure you understand what the code is doing on both sides.

package filesendtest;

import java.io.*;
import java.net.*;

class TCPServer {

private final static String fileToSend = "C:\\test1.pdf";

public static void main(String args[]) {

while (true) {
ServerSocket welcomeSocket = null;
Socket connectionSocket = null;
BufferedOutputStream outToClient = null;

try {
welcomeSocket = new ServerSocket(3248);
connectionSocket = welcomeSocket.accept();
outToClient = new BufferedOutputStream(connectionSocket.getOutputStream());
} catch (IOException ex) {
// Do exception handling
}

if (outToClient != null) {
File myFile = new File( fileToSend );
byte[] mybytearray = new byte[(int) myFile.length()];

FileInputStream fis = null;

try {
fis = new FileInputStream(myFile);
} catch (FileNotFoundException ex) {
// Do exception handling
}
BufferedInputStream bis = new BufferedInputStream(fis);

try {
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
outToClient.flush();
outToClient.close();
connectionSocket.close();

// File sent, exit the main method
return;
} catch (IOException ex) {
// Do exception handling
}
}
}
}
}

package filesendtest;

import java.io.*;
import java.io.ByteArrayOutputStream;
import java.net.*;

class TCPClient {

private final static String serverIP = "127.0.0.1";
private final static int serverPort = 3248;
private final static String fileOutput = "C:\\testout.pdf";

public static void main(String args[]) {
byte[] aByte = new byte[1];
int bytesRead;

Socket clientSocket = null;
InputStream is = null;

try {
clientSocket = new Socket( serverIP , serverPort );
is = clientSocket.getInputStream();
} catch (IOException ex) {
// Do exception handling
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();

if (is != null) {

FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream( fileOutput );
bos = new BufferedOutputStream(fos);
bytesRead = is.read(aByte, 0, aByte.length);

do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);

bos.write(baos.toByteArray());
bos.flush();
bos.close();
clientSocket.close();
} catch (IOException ex) {
// Do exception handling
}
}
}
}

Related

Byte array of unknown length in java

Edit: The following could be used to fingerprint small files before and after transfer (use SHA if you feel it's necessary):

public static String md5String(File file) {
try {
InputStream fin = new FileInputStream(file);
java.security.MessageDigest md5er = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
int read;
do {
read = fin.read(buffer);
if (read > 0) {
md5er.update(buffer, 0, read);
}
} while (read != -1);
fin.close();
byte[] digest = md5er.digest();
if (digest == null) {
return null;
}
String strDigest = "0x";
for (int i = 0; i < digest.length; i++) {
strDigest += Integer.toString((digest[i] & 0xff)
+ 0x100, 16).substring(1).toUpperCase();
}
return strDigest;
} catch (Exception e) {
return null;
}
}

Client Server File Transfer Java

This isn't really an "algorithm" question; you're designing a (simple) protocol. What you've described sounds reasonable, but it's too vague to implement. You need to be more specific. For example, some things you need to decide:

  • How does the receiving program know what filename it should save to? Should that be sent through the socket, or should it just ask the user?
  • How is the file size transmitted?
    • Is it a character string? If so, how is its length indicated? (With a null terminator? A newline?)
    • Is it a binary value? If so, how big? (32 bits or 64?) What endianness?
  • What does "broken down in parts" mean? If you're writing to a TCP socket, you don't need to worry about packet boundaries; TCP takes care of that.
  • Does the recipient send anything back, like a success or failure indication?
  • What happens when the whole file has been transmitted?
    • Should both ends assume that the connection must be closed?
    • Or can you send multiple files through a single connection? If so, how does the sender indicate that another file will follow?

Also, you're using the terms "client" and "server" backward. Typically the "client" is the machine that initiates a connection to a server, and the "server" is the machine that waits for connections from clients.

Java multiple file transfer over socket

You are reading the socket until read() returns -1. This is the end-of-stream condition (EOS). EOS happens when the peer closes the connection. Not when it finishes writing one file.

You need to send the file size ahead of each file. You're already doing a similar thing with the file count. Then make sure you read exactly that many bytes for that file:

String filename = dis.readUTF();
long fileSize = dis.readLong();
FileOutputStream fos = new FileOutputStream(filename);
while (fileSize > 0 && (n = dis.read(buf, 0, (int)Math.min(buf.length, fileSize))) != -1)
{
fos.write(buf,0,n);
fileSize -= n;
}
fos.close();

You can enclose all this in a loop that terminates when readUTF() throws EOFException. Conversely of course you have to call writeUTF(filename) and writeLong(filesize) at the sender, before sending the data.

File transfer Client to Client in JAVA

I was able to make a transfer between two clients easily with the information provided and a little research on stackOverflow to understand more about out/inputStreams!
This post also helped me a lot: Sending a file with Java Sockets, losing data
next step is the shared transfer

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

The correct way to copy a stream in Java is as follows:

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.

How to transfer multiple files between client and server?

You suggest HTTP as a protocol for your clients and servers -- HTTP is a fine protocol but may be a large implementation hurdle if you want to do the whole thing yourself. The HTTP PUT verb can be used to upload a file, and the benefit of using HTTP in this fashion is that your client and server could communicate with other tools designed to use PUT requests. (PUT is less-used than other HTTP verbs, so not all HTTP tools will work; the curl(1) program does support PUT via the -T command line option. This will be a great implementation aid, should you chose HTTP.)

There are a variety of REST Frameworks that can assist you in writing HTTP software; I have heard good things about Restlet, it would be my recommended starting point.

But you don't have to pick HTTP as your protocol. I think you can learn a lot about networking programming if you implement your own protocol -- it will teach you a lot about API design and sockets programming in a way that would be difficult to learn by using pre-written HTTP protocol tools (and frustrating if you tried to implement HTTP in its entirety yourself).

Consider this conversation:

client -> server: upload file named "flubber" sized 200000 bytes

server -> client: ok

client -> server: flubber contents
server -> client: ok

client -> server: upload file named "blort" sized 10 bytes

server -> client: error, file exists

...

You might want to add new commands to provide for hashing the file on both ends to ensure the file transfer succeeded, commands for sending specific byte ranges (either to append to an existing file or re-start a failed transfer), commands to list existing file names on the server, commands to overwrite existing files, commands to delete files from the server, and so forth. The best part of writing your own protocol is you get to decide what your programs will support. The downside is that you get to test the features you write, and testing some cases may be difficult. (Say, consider that a client may send each character of a command in a different TCP packet. Implementing the buffering to store up an entire command isn't trivial, but it is already done for you with a tool such as Restlet.)

Juan's advice to use multiple TCP sessions isn't strictly necessary -- though it may be the easiest path forward for you. You'll need to add some mechanism to provide the filename to the remote peer, and that might be best done through the "control" channel (the first session running -- similar to FTP) or it might be something you send immediately before the file's contents (similar to HTTP).

I'd like to suggest avoiding multiple connections, though -- each connection requires three times the round-trip time between systems to set up and start transferring bytes. This delay can be extremely annoying, especially when you're trying to transfer hundreds of small files. You can even spend more time setting up connections than you do actually sending data.

But it's your tool -- you get to design it as you wish. Have fun.

Java file transfer file to server

You did not get InputStream from the socket after serverSocket.accept(). Open InputStream on the socket.

    clientSocket = serverSocket.accept();

InputStream in = clientSocket.getInputStream();

// Writing the file to disk
// Instantiating a new output stream object
OutputStream output = new FileOutputStream("YourFile.zip");

byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
// Closing the FileOutputStream handle
output.close();

Refer to working example at : Write and Read File over Socket

File Transfer from Server to Client using java sockets. Error on Server side and File transferred to client is empty

See with binary data you have change the readers as they are capable of only characters and do not work with byte stream. moreover readline means read till end of line and in binary files ('\n') does not make too much sense.

This is from documentation of printWriter

It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams.

What you would want now is to use byte arrays and write them as chunks like this :

import java.io.*;
import java.net.*;
import java.util.*;
public class ft2server
{

public static void main(String args[])throws IOException
{
ServerSocket ss=null;
try
{
ss=new ServerSocket(8085);
}
catch(IOException e)
{
System.out.println("couldn't listen");
System.exit(0);
}
Socket cs=null;
try
{
cs=ss.accept();
System.out.println("Connection established"+cs);
}
catch(Exception e)
{
System.out.println("Accept failed");
System.exit(1);
}
BufferedOutputStream put=new BufferedOutputStream(cs.getOutputStream());
BufferedReader st=new BufferedReader(new InputStreamReader(cs.getInputStream()));
String s=st.readLine();
String str = "/home/milind/Desktop/";
String path = str + s;
System.out.println("The requested file is path: "+path);
System.out.println("The requested file is : "+s);
File f=new File(path);
if(f.isFile())
{
FileInputStream fis=new FileInputStream(f);

byte []buf=new byte[1024];
int read;
while((read=fis.read(buf,0,1024))!=-1)
{
put.write(buf,0,read);
put.flush();
}
//d.close();
System.out.println("File transfered");
cs.close();
ss.close();
}
}
}

The client

import java.io.*;
import java.net.*;
import java.util.*;
public class ft2client
{
public static void main(String srgs[])throws IOException
{
Socket s=null;
BufferedInputStream get=null;
PrintWriter put=null;
try
{
s=new Socket("127.0.0.1",8085);
get=new BufferedInputStream(s.getInputStream());
put=new PrintWriter(s.getOutputStream(),true);

String f;
int u;
System.out.println("Enter the file name to transfer from server:");
DataInputStream dis=new DataInputStream(System.in);
f=dis.readLine();
put.println(f);
File f1=new File(f);
String str = "/home/milind/";
FileOutputStream fs=new FileOutputStream(new File(str,f1.toString()));
byte jj[]=new byte[1024];
while((u=get.read(jj,0,1024))!=-1)
{
fs.write(jj,0,u);
}
fs.close();
System.out.println("File received");
s.close();
}catch(Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
}


Related Topics



Leave a reply



Submit