简体   繁体   中英

Program for file transfer in java using sockets

I have written a java code to transfer files from one server to another using the concept of socket programming. I got the codes from another java forum that meet my requirements. The program is said to transfer large sized files (like .mkv , .mprg movies) from one machine to another and can be used to transfer files of all formats. But after running the codes I found that the program is not able to transfer large sized files such as movies and even pdf of sizes 80mb or 111mb. The program has used bytebuffer but still error occurs. The codes are as follows (I got them from this site http://www.coderpanda.com/java-socket-programming-transferring-large-sized-files-through-socket/ )

ClientMain.java

 import java.io.IOException; 
import java.net.Socket;   
public class ClientMain 
{     
private DirectoryTxr transmitter = null;     
Socket clientSocket = null;     
private boolean connectedStatus = false;     
private String ipAddress;     
String srcPath = null;     
String dstPath = "";     
public ClientMain() 
{       
}       
public void setIpAddress(String ip) 
{         
this.ipAddress = ip;     
}       
public void setSrcPath(String path) 
{         
this.srcPath = path;     
}       
public void setDstPath(String path) 
{         
this.dstPath = path;     
}       
private void createConnection() 
{         
Runnable connectRunnable = new Runnable() 
{             
public void run() 
{                 
while (!connectedStatus) 
{                     
try 
{                         
clientSocket = new Socket(ipAddress, 22);                         
connectedStatus = true;                         
transmitter = new DirectoryTxr(clientSocket, srcPath, dstPath);                     
} 
catch (IOException io) 
{                         
io.printStackTrace();                     
}                 
}               
}         
};         
Thread connectionThread = new Thread(connectRunnable);         
connectionThread.start();     
}       
public static void main(String[] args) 
{      
ClientMain main = new ClientMain();         
main.setIpAddress("localHost");         
main.setSrcPath("C:/Transfer/");         
main.setDstPath("C:/Receive");         
main.createConnection();       
} 
}

DirectoryTxr.java

import java.io.*; 
import java.net.Socket; 
import java.net.SocketException; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel;   

public class DirectoryTxr 
{    
Socket clientSocket = null;     
String srcDir = null;     
String dstDir = null;     
byte[] readBuffer = new byte[1024];     
private InputStream inStream = null;     
private OutputStream outStream = null;     
int state = 0;     
final int permissionReqState = 1;     
final int initialState = 0;     
final int dirHeaderSendState = 2;     
final int fileHeaderSendState = 3;     
final int fileSendState = 4;     
final int fileFinishedState = 5;     
private boolean isLive = false;     
private int numFiles = 0;     
private int filePointer = 0;     
String request = "May I send?";     
String respServer = "Yes,You can";     
String dirResponse = "Directory created...Please send files";     
String fileHeaderRecvd = "File header received ...Send File";     
String fileReceived = "File Received";     
String dirFailedResponse = "Failed";     
File[] opFileList = null;       

public DirectoryTxr(Socket clientSocket, String srcDir, String dstDir) 
{           
try 
{             
this.clientSocket = clientSocket;             
inStream = clientSocket.getInputStream();             
outStream = clientSocket.getOutputStream();             
isLive = true;             
this.srcDir = srcDir;             
this.dstDir = dstDir;             
state = initialState;            
readResponse();             
sendMessage(request);             
state = permissionReqState;         
} 
catch (IOException io) 
{             
io.printStackTrace();         
}         
}       
private void sendMessage(String message) 
{         
try 
{             
sendBytes(request.getBytes("UTF-8"));         
} 
catch (UnsupportedEncodingException e) 
{             
e.printStackTrace();         
}     
}      
private void readResponse() 
{        
Runnable readRunnable = new Runnable() 
{             
public void run() 
{                 
while (isLive) 
{                     
try 
{                         
int num = inStream.read(readBuffer);                         
if (num > 0) 
{                             
byte[] tempArray = new byte[num];                             
System.arraycopy(readBuffer, 0, tempArray, 0, num);                             
processBytes(tempArray);                         
}                     
} 
catch (SocketException se) 
{                         
System.exit(0);                     
} 
catch (IOException io) 
{                         
io.printStackTrace();                         
isLive = false;                     
}                 
}             
}         
};         
Thread readThread = new Thread(readRunnable);         
readThread.start();       
}       
private void sendDirectoryHeader() 
{         
File file = new File(srcDir);         
if (file.isDirectory()) 
{             
try 
{                 
String[] childFiles = file.list();                 
numFiles = childFiles.length;                 
String dirHeader = "$" + dstDir + "#" + numFiles + "&";                 
sendBytes(dirHeader.getBytes("UTF-8"));             
} 
catch (UnsupportedEncodingException en) 
{                 
en.printStackTrace();             
}         
} 
else 
{             
System.out.println(srcDir + " is not a valid directory");         
}    
}         
private void sendFile(String dirName) 
{         
File file = new File(dirName);           
if (!file.isDirectory()) 
{             
try 
{                 
int len = (int) file.length();                 
int buffSize = len / 8;                                 
RandomAccessFile raf = new RandomAccessFile(file, "rw");                 
FileChannel channel = raf.getChannel();                   
int numRead = 0;                 
while (numRead >= 0) 
{                     
ByteBuffer buf = ByteBuffer.allocate(1024 * 100000);                     
numRead = channel.read(buf);                     
if (numRead > 0) 
{                         
byte[] array = new byte[numRead];                         
System.arraycopy(buf.array(), 0, array, 0, numRead);                         
sendBytes(array);                     
}                 
}                 
System.out.println("Finished");               
} 
catch (IOException io) 
{                 
io.printStackTrace();             
}           
}      
}       
private void sendHeader(String fileName) 
{         
try 
{             
File file = new File(fileName);             
if (file.isDirectory())                 
return;          
String header = "&" + fileName + "#" + file.length() + "*";             
sendHeader(header);               
sendBytes(header.getBytes("UTF-8"));         
} 
catch (UnsupportedEncodingException e) 
{             
e.printStackTrace();         
}     
}       
private void sendBytes(byte[] dataBytes) 
{         
synchronized (clientSocket) 
{             
if (outStream != null) 
{                 
try 
{                     
outStream.write(dataBytes);                     
outStream.flush();                 
} 
catch (IOException io) 
{                     
io.printStackTrace();                 
}             
}         
}       
}       
private void processBytes(byte[] data) 
{         
try 
{             
String parsedMessage = new String(data, "UTF-8");             
System.out.println(parsedMessage);             
setResponse(parsedMessage);         
} 
catch (UnsupportedEncodingException u) 
{             
u.printStackTrace();         
}     
}       
private void setResponse(String message) 
{         
if (message.trim().equalsIgnoreCase(respServer) && state == permissionReqState) 
{             
state = dirHeaderSendState;             
sendDirectoryHeader();             
} 
else if (message.trim().equalsIgnoreCase(dirResponse) && state == dirHeaderSendState) 
{             
state = fileHeaderSendState;             
if (LocateDirectory()) 
{                 
createAndSendHeader();             
} 
else 
{                 
System.out.println("Vacant or invalid directory");             
}             
} 
else if (message.trim().equalsIgnoreCase(fileHeaderRecvd) && state == fileHeaderSendState) 
{             
state = fileSendState;             
sendFile(opFileList[filePointer].toString());             
state = fileFinishedState;             
filePointer++;           
} 
else if (message.trim().equalsIgnoreCase(fileReceived) && state == fileFinishedState) 
{             
if (filePointer < numFiles) 
{                 
createAndSendHeader();             
}             
System.out.println("Successfully sent");           
} 
else if (message.trim().equalsIgnoreCase(dirFailedResponse)) 
{             
System.out.println("Going to exit....Error ");                  
} 
else if (message.trim().equalsIgnoreCase("Thanks")) 
{             
System.out.println("All files were copied");         
}       
}       
private void closeSocket() 
{         
try 
{             
clientSocket.close();         
} 
catch (IOException e) 
{             
e.printStackTrace();         
}     
}         
private boolean LocateDirectory() 
{         
boolean status = false;         
File file = new File(srcDir);         
if (file.isDirectory()) 
{             
opFileList = file.listFiles();             
numFiles = opFileList.length;             
if (numFiles <= 0) 
{                 
System.out.println("No files found");             
} 
else 
{                 
status = true;             
}           
}         
return status;     
}       
private void createAndSendHeader() 
{         
File opFile = opFileList[filePointer];         
String header = "&" + opFile.getName() + "#" + opFile.length() + "*";         
try 
{             
state = fileHeaderSendState;             
sendBytes(header.getBytes("UTF-8"));           
} 
catch (UnsupportedEncodingException e) 
{           
}     
}       
private void sendListFiles() 
{         
createAndSendHeader();       
} 
} 

ServerMain.java

public class ServerMain {      
 public ServerMain() {    
   }    
   public static void main(String[] args) {        
   DirectoryRcr dirRcr = new DirectoryRcr();     
  } 
} 

DirectoryRcr.java

import java.io.*; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.SocketException;   

public class DirectoryRcr 
{      
 String request = "May I send?";     
String respServer = "Yes,You can";     
String dirResponse = "Directory created...Please send files";     
String dirFailedResponse = "Failed";     
String fileHeaderRecvd = "File header received ...Send File";     
String fileReceived = "File Received";     
Socket socket = null;     
OutputStream ioStream = null;     
InputStream inStream = null;     
boolean isLive = false;    
int state = 0;     
final int initialState = 0;     
final int dirHeaderWait = 1;     
final int dirWaitState = 2;     
final int fileHeaderWaitState = 3;    
final int fileContentWaitState = 4;     
final int fileReceiveState = 5;     
final int fileReceivedState = 6;    
final int finalState = 7;     
byte[] readBuffer = new byte[1024 * 100000];     
long fileSize = 0;     
String dir = "";     
FileOutputStream foStream = null;     
int fileCount = 0;     
File dstFile = null;       
public DirectoryRcr() 
{         
acceptConnection();     
} 
private void acceptConnection() 
{         
try 
{             
ServerSocket server = new ServerSocket(22);             
socket = server.accept();             
isLive = true;             
ioStream = socket.getOutputStream();             
inStream = socket.getInputStream();            
state = initialState;             
startReadThread();           
} 
catch (IOException io) 
{             
io.printStackTrace();         
}     
}       
private void startReadThread() 
{         
Thread readRunnable = new Thread() 
{             
public void run() 
{                 
while (isLive) 
{                     
try 
{                         
int num = inStream.read(readBuffer);                         
if (num > 0) 
{                             
byte[] tempArray = new byte[num];                             
System.arraycopy(readBuffer, 0, tempArray, 0, num);                             
processBytes(tempArray);                         
}                         
sleep(100);                       
} catch (SocketException s) 
{                      
}
catch (IOException e)
 {                         
e.printStackTrace();                     
} 
catch (InterruptedException i) 
{                         
i.printStackTrace();                     
}                 
}             
}         
};         
Thread readThread = new Thread(readRunnable);         
readThread.start();     
}       
private void processBytes(byte[] buff) throws InterruptedException 
{         
if (state == fileReceiveState || state == fileContentWaitState) 
{                      
if (state == fileContentWaitState)                 
state = fileReceiveState;             
fileSize = fileSize - buff.length;             
writeToFile(buff);                 
if (fileSize == 0) 
{                 
state = fileReceivedState;                 
try 
{                     
foStream.close();                 
} 
catch (IOException io) 
{                     
io.printStackTrace();                 
}                 
System.out.println("Received " + dstFile.getName());                 
sendResponse(fileReceived);                 
fileCount--;                 
if (fileCount != 0) 
{                     
state = fileHeaderWaitState;                 
} 
else 
{                     
System.out.println("Finished");                     
state = finalState;                     
sendResponse("Thanks");                     
Thread.sleep(2000);                     
System.exit(0);                 
}                   
System.out.println("Received");             
}         
} 
else 
{             
parseToUTF(buff);         
}       
}       
private void parseToUTF(byte[] data) 
{         
try 
{             
String parsedMessage = new String(data, "UTF-8");             
System.out.println(parsedMessage);             
setResponse(parsedMessage);        
 } 
catch (UnsupportedEncodingException u) {             
u.printStackTrace();         
}       
}       
private void setResponse(String message) 
{         
if (message.trim().equalsIgnoreCase(request) && state == initialState) 
{             
sendResponse(respServer);             
state = dirHeaderWait;           
} 
else if (state == dirHeaderWait) 
{             
if (createDirectory(message)) 
{                 
sendResponse(dirResponse);                 
state = fileHeaderWaitState;             
} 
else 
{                 
sendResponse(dirFailedResponse);                 
System.out.println("Error occurred...Going to exit");                 
System.exit(0);             
}             
} else if (state == fileHeaderWaitState) 
{             
createFile(message);             
state = fileContentWaitState;             
sendResponse(fileHeaderRecvd);           
} 
else if (message.trim().equalsIgnoreCase(dirFailedResponse)) 
{             
System.out.println("Error occurred ....");             
System.exit(0);         
}       
}       
private void sendResponse(String resp) 
{         
try 
{             
sendBytes(resp.getBytes("UTF-8"));         
} 
catch (UnsupportedEncodingException e) 
{             
e.printStackTrace();         
}     
}       
private boolean createDirectory(String dirName) 
{         
boolean status = false;         
dir = dirName.substring(dirName.indexOf("$") + 1, dirName.indexOf("#"));         
fileCount = Integer.parseInt(dirName.substring(dirName.indexOf("#") + 1, dirName.indexOf("&")));         
if (new File(dir).mkdir()) 
{             
status = true;             
System.out.println("Successfully created directory  " + dirName);         
} 
else if (new File(dir).mkdirs()) 
{             
status = true;             
System.out.println("Directories were created " + dirName);           
} 
else if (new File(dir).exists()) 
{             
status = true;             
System.out.println("Directory exists" + dirName);        
 } 
else 
{             
System.out.println("Could not create directory " + dirName);             
status = false;         
}           
return status;     
}       
private void createFile(String fileName) 
{           
String file = fileName.substring(fileName.indexOf("&") + 1, fileName.indexOf("#"));         
String lengthFile = fileName.substring(fileName.indexOf("#") + 1, fileName.indexOf("*"));         
fileSize = Integer.parseInt(lengthFile);         
dstFile = new File(dir + "/" + file);         
try 
{             
foStream = new FileOutputStream(dstFile);             
System.out.println("Starting to receive " + dstFile.getName());         
} 
catch (FileNotFoundException fn) 
{             
fn.printStackTrace();         
}       
}       
private void writeToFile(byte[] buff) 
{         
try 
{             
foStream.write(buff);         
} 
catch (IOException io) 
{             
io.printStackTrace();         
}     
}       
private void sendBytes(byte[] dataBytes) 
{         
synchronized (socket) 
{             
if (ioStream != null) 
{                 
try 
{                     
ioStream.write(dataBytes);                 
} 
catch (IOException io) 
{                    
 io.printStackTrace();                
}             
}         
}       
}   
} 

Note that:-

  1. ClientMain.java and DirectoryTxr.java are the two classes under client application.
  2. ServerMain.java and DirectoryRcr.java are the two classes under Server application.
  3. run the ClientMain.java and ServerMain.java simultaneously

Also specify the source directory, destination directory and host address of the machine in which server is running in the ClientMain.java(as per your computer). Here we are not specifying source file ,instead a source directory or folder is specifying.So the entire files of source directory will be transferred.

I would really appreciate if someone can help me with the problem.

You can check this code. This code can send files till 2GB of file size. Checked and working. Basically what I do here is first I send the file size and file name in an object then I start sending the file. First of all let me show you the class whose object will carry the File's details and send it to Receiver.

FileTransfer Class:

public class FileDetails implements Serializable {

String name;
long size;

public void setDetails(String name, long size) {
    this.name = name;
    this.size = size;
}

public String getName() {
    return name;
}

public long getSize() {
    return size;
}
}

Sender:

ServerSocket sendServer = null;
    Socket sendSocket;
    FileDetails details;
    byte data[];
    try {
        File file = new File("File Url");

        // Getting file name and size
        if (file.length() > Integer.MAX_VALUE) {
            System.out.println("File size exceeds 2 GB");
        } else {
            sendServer = new ServerSocket(5050);
            System.out.println("Waiting for Client...");
            sendSocket = sendServer.accept();
            // File Object for accesing file Details
            System.out.println("Connected to Client...");
            data = new byte[2048]; // Here you can increase the size also which will send it faster
            details = new FileDetails();
            details.setDetails(file.getName(), file.length());

            // Sending file details to the client
            System.out.println("Sending file details...");
            ObjectOutputStream sendDetails = new ObjectOutputStream(sendSocket.getOutputStream());
            sendDetails.writeObject(details);
            sendDetails.flush();
            // Sending File Data 
            System.out.println("Sending file data...");
            FileInputStream fileStream = new FileInputStream(file);
            BufferedInputStream fileBuffer = new BufferedInputStream(fileStream);
            OutputStream out = sendSocket.getOutputStream();
            int count;
            while ((count = fileBuffer.read(data)) > 0) {
                System.out.println("Data Sent : " + count);
                out.write(data, 0, count);
                out.flush();
            }
            out.close();
            fileBuffer.close();
            fileStream.close();
        }
    } catch (Exception e) {
        System.out.println("Error : " + e.toString());
    }

Receiver's code :

int port = 5050;
    try {
        System.out.println("Connecting to Server...");
        Socket receiveSocket = new Socket("IP of Server", port);
        System.out.println("Connected to Server...");
        // Getting file details

        System.out.println("Getting details from Server...");
        ObjectInputStream getDetails = new ObjectInputStream(receiveSocket.getInputStream());
        FileDetails details = (FileDetails) getDetails.readObject();
        System.out.println("Now receiving file...");
        // Storing file name and sizes

        String fileName = details.getName();
        System.out.println("File Name : " + fileName);
        byte data[] = new byte[2048]; // Here you can increase the size also which will receive it faster
        FileOutputStream fileOut = new FileOutputStream("D:\\" + fileName);
        InputStream fileIn = receiveSocket.getInputStream();
        BufferedOutputStream fileBuffer = new BufferedOutputStream(fileOut);
        int count;
        int sum = 0;
        while ((count = fileIn.read(data)) > 0) {
            sum += count;
            fileBuffer.write(data, 0, count);
            System.out.println("Data received : " + sum);
            fileBuffer.flush();
        }
        System.out.println("File Received...");
        fileBuffer.close();
        fileIn.close();
    } catch (Exception e) {
        System.out.println("Error : " + e.toString());
    }

Hope this helps you.

You don't need all this. The canonical way to copy a stream in Java is as follows. It works for any buffer size greater than zero. I generally use 8192. There is certainly no necessity to read entire files into memory. It just wastes time and space.

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

If you know the size in advance and need to keep the socket open for another transfer:

while (total < length && (count = in.read(buffer, 0, length-total > buffer.length ? buffer.length : (int)(length-total))) > 0)
{
    out.write(buffer, 0, count);
    total += count;
}

where total is a long initialized to zero before this loop, and length is the length you know in advance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM