I need to copy and paste dynamically incrementing log file data from FTP Server to local drive.
The below program I used can only do the copying one time. And not in the incremental manner.
public class ReadFtpFile {
public static void main(String[] args) throws UnknownHostException {
String server = "myIP";
int port = 20;
String user = "username";
String pass = "password";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// APPROACH #2: using InputStream retrieveFileStream(String)
String remoteFile2 = "/folder/myfile.log";
File downloadFile2 = new File("F:/myfolder/mylogfile.log");
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
outputStream2.write(bytesArray, 0, bytesRead);
}
Boolean success = ftpClient.completePendingCommand();
if (success) {
System.out.println("File #2 has been downloaded successfully.");
}
outputStream2.close();
inputStream.close();
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
The log file data in the FTP server is growing for every second.I need to update the local file with new data in the FTP.
Replace the lines
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
with
ftpClient.setRestartOffset(downloadFile2.length());
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2, true));
This will check if the file already exists and, if so, download only the new data. If you need to do this periodically, add a loop around the whole try-catch block.
You need to update your code with Java threads and combine while loops to schedule this program for desired time.
String remoteFile2 = "/folder/myfile.log";
File downloadFile2 = new File("F:/myfolder/mylogfile.log");
OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
int minutecount=0;
while(minutecount==120){
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
outputStream2.write(bytesArray, 0, bytesRead);
}
// Here i sceduled for every 1 minute
Thread.sleep(60*1000);
minutecount++;
}
Boolean success = ftpClient.completePendingCommand();
if (success) {
System.out.println("File #2 has been downloaded successfully.");
}
outputStream2.close();
inputStream.close();`
Related
So I have this thing that I'm making and the problem is that I think that some bytes are lost while the file is compressed and send to server as well as saved locally. I was able to send data while not using ByteArrayOutputStream but I have to use it and can't just use socket's OutputStream directly as I need each sent file to have somwhat unique ID. Also sizes of out.zip and out2.zip are different by around 10kB (out2.zip is smaller)
here is Log dump: https://pastebin.com/UyTqnRYc
Function that sends data in chunks
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipParameters zipParameters = buildZipParameters(compressionMethod);
ObjectOutputStream objOS = new ObjectOutputStream(outputStream);
File f = new File("out2.zip");
FileOutputStream fos = new FileOutputStream(f);
for (File directory:pathsToDirectories) {
String relativeRootDirectory = directory.getName();
List<File> filesAndDirectories = Arrays.stream(Objects.requireNonNull(directory.listFiles())).toList();
for (File somefile:filesAndDirectories) {
if(somefile.isDirectory()){
addDirectoryToZip(zos,somefile,zipParameters,relativeRootDirectory,rootDirectoryName);
}
else
{
if (zipParameters.getCompressionMethod() == CompressionMethod.STORE) {
zipParameters.setEntrySize(somefile.length());
}
byte[] buff = new byte[4096];
zipParameters.setFileNameInZip(rootDirectoryName+ "/"+somefile.getName()); //YIKES
zos.putNextEntry(zipParameters);
try(InputStream inputStream = new FileInputStream(somefile)) {
int readLen;
while (((readLen = inputStream.read(buff)) != -1)) {
zos.write(buff);
byte[] b = baos.toByteArray();
System.out.println("written :"+baos.toByteArray().length);
objOS.writeObject(new TransportDataModel((byte) 1,baos.toByteArray()));
fos.write(baos.toByteArray());
baos.reset();
baos.flush();
}
}
zos.closeEntry();
}
}
}
objOS.writeObject(new TransportDataModel((byte) 1,baos.toByteArray()));
zos.flush();
System.out.println("REST OF IT :"+ Arrays.toString(baos.toByteArray()));
System.out.println(baos.toByteArray().length);
objOS.writeObject(new TransportDataModel((byte) 1,baos.toByteArray()));
fos.write(baos.toByteArray());
baos.reset();
System.out.println("REST OF IT :"+ Arrays.toString(baos.toByteArray()));
fos.flush();
fos.close();
objOS.writeObject(new TransportDataModel((byte) -1,new byte[0]));
zos.close();
}
Record used as a packet
import java.io.Serializable;
public record TransportDataModel(byte id, byte[] data) implements Serializable {
}
Server code:
public Server(int port)
{
// starts server and waits for a connection
try
{
server = new ServerSocket(port);
System.out.println("Server started");
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted");
in = new ObjectInputStream(socket.getInputStream());
File f = new File("out.zip");
FileOutputStream outputStream = new FileOutputStream(f);
TransportDataModel transportDataModel;
while (true) {
transportDataModel= (TransportDataModel) in.readObject();
if (transportDataModel.id() == -1) {
break;
}
if(transportDataModel.data().length != 0)
{
//System.out.println(transportDataModel.id());
outputStream.write(transportDataModel.data());
}
}
outputStream.flush();
outputStream.close();
System.out.println("Closing connection");
// close connection
socket.close();
in.close();
ZipFile zipFile = new ZipFile("out.zip");
zipFile.extractAll("/home/xenu/IdeaProjects/BBT-BasicBackupTool");
}
catch(IOException i)
{
i.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
I have been given a assignment to create a Dropbox like file multi client single server file transfer application. So I created a Server application in java that runs continuously to accept connections from clients and give each client it's own thread so they can all work concurrently. The Clients on the other hand monitor a predesignated folder for any new file additions. As soon as they detect a new file they send it to server. When the server receives a file it will then send that file to all connected clients.
My PROBLEM is that the client code runs okay during debugging but when run normally it gives the error:
Error: java.io.FileNotFoundException: D:\Distributed Systems\Labs\Lab_1\client_1\shared_directory\random.txt (The process cannot access the file because it is being used by another process)
after some debugging I realized that this error is happening because the client code is too fast and that's why I had to make it slow artificially by adding Thread.sleep().
What can I do to ensure that the client waits for the file to be properly added to the monitored folder before attempting to send it to the server ?.
I am using java.nio.file Watch Service API to monitor the folder for new or modified files.
The Serve code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FT_Server {
// Vector to store active clients
static Vector<ClientHandler> connectedClients = new Vector<>();
static ArrayList<String> clientNames = new ArrayList<>();
public static void main(String[] args) throws Exception {
String userName = "";
try (ServerSocket serverSocket = new ServerSocket(59898)) {
System.out.println("Server is running, waiting for connection");
ExecutorService pool = Executors.newFixedThreadPool(20);
while (true) {
//client socket created
Socket clientSocket = serverSocket.accept();
//obtain input and output streams
DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
DataOutputStream dos = new DataOutputStream(clientSocket.getOutputStream());
userName = dis.readUTF();
System.out.println(userName);
// check if username already exists
for (ClientHandler clt : FT_Server.connectedClients) {
clientNames.add(clt.cltName);
}
while (clientNames.contains(userName)) {
dos.writeUTF("FALSE");
userName = dis.readUTF();
}
dos.writeUTF("TRUE");
System.out.println("Creating a new handler for this client...");
// Create a new handler object for handling this request.
ClientHandler clt = new ClientHandler(clientSocket, userName);
//add the new client handler object to the vector of connected clients
connectedClients.add(clt);
clientNames.add(userName);
System.out.println(connectedClients);
System.out.println(clientNames);
pool.execute(clt);
}
} catch(IOException ioe){
ioe.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
DataInputStream dis = null;
DataOutputStream dos = null;
FileOutputStream fos = null;
Socket cltSocket;
String cltName;
FileInputStream fis = null;
BufferedInputStream bis = null;
InputStream in = null;
boolean isloggedin;
ClientHandler(Socket clientSocket, String userName) {
this.cltSocket = clientSocket;
this.cltName = userName;
this.isloggedin=true;
}
#Override
public void run() {
System.out.println("inside ClientHandler class's run method");
String fileName = "";
int bytesRead = 0;
while (true){
try {
// receive file from client
dis = new DataInputStream(cltSocket.getInputStream());
dos = new DataOutputStream(cltSocket.getOutputStream());
if (dis != null)
System.out.println("dis not null");
//get the name of the file
fileName = dis.readUTF();
System.out.println("fileName = "+fileName);
if(fileName.equals("logout")){
this.isloggedin=false;
this.cltSocket.close();
break;
}
fos = new FileOutputStream("D:/Distributed Systems/Labs/Lab_1/server/" + fileName);
//get the size of the file to be received
long size = dis.readLong();
System.out.println("size = "+size);
byte[] buffer = new byte[(int) size];
//write the data bytes received to a file
while (size > 0 && (bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
fos.write(buffer, 0, bytesRead);
size -= bytesRead;
}
System.out.println("File " + fileName + " downloaded from client(" + size + " bytes read)");
} catch (IOException e1) {
e1.printStackTrace();
}
//send the file to all the connected clients
final String FILE_TO_SEND = "D:/Distributed Systems/Labs/Lab_1/server/" + fileName;
try {
System.out.println("inside sending file to connected clients try section");
File myFile = new File(FILE_TO_SEND);
byte[] fileContents = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
// disB = new DataInputStream(bis);
if (bis != null){
System.out.println("bis not null");
}
//fill the data into the Byte array?
bis.read(fileContents, 0, fileContents.length);
// Sending file to each connected client
for (ClientHandler clt : FT_Server.connectedClients) {
System.out.println("inside for loop");
if (clt.cltName != this.cltName && clt.isloggedin==true){
System.out.println("inside if");
//Send the file name to the client
clt.dos.writeUTF(myFile.getName());
//send the length of the file to the client
clt.dos.writeLong(fileContents.length);
System.out.println("Sending the file" + FILE_TO_SEND + "(" + fileContents.length + " bytes)");
//send the file contents to the client?
clt.dos.write(fileContents, 0, fileContents.length);
clt.dos.flush();
// // Sending file data to the client?
// os.write(fileContents, 0, fileContents.length);
// os.flush();
System.out.println("File sent to client = "+clt.cltName);
}
}
} catch (Exception e) {
System.out.println("Error: " + e + "for client socket: " + cltSocket);
}
}
try {
System.out.println("inside finally");
dis.close();
dos.close();
fos.close();
fis.close();
bis.close();
cltSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Client code:
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.file.*;
import java.util.Scanner;
public class FT_Client_1 {
Socket clientSocket = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public static void main(String[] args) throws Exception {
FT_Client_1 clt = new FT_Client_1();
clt.startConnection();
clt.runClient();
// clt.closeConnection();
}
public void runClient() {
System.out.println("inside runClient()");
//monitor the shared directory and send any new files to the server
MonitorSharedDirectory mon = new MonitorSharedDirectory();
Thread t1 = new Thread(mon);
t1.start();
// Receive any files sent by the server
receiveFileFromServer rec = new receiveFileFromServer();
Thread t2 = new Thread(rec);
t2.start();
}
public void startConnection() throws UnknownHostException, IOException {
System.out.println("inside startConnection()");
String username = "";
Boolean valid = true;
// taking username as input from the user
Scanner sc = new Scanner(System.in);
System.out.println("Enter a username:");
username = sc.nextLine();
//creating client socket
clientSocket = new Socket("127.0.0.1", 59898);
//getting the data input and output stream using client socket
dos = new DataOutputStream(clientSocket.getOutputStream());
dis = new DataInputStream(clientSocket.getInputStream());
dos.writeUTF(username);
System.out.println("after sending username to the server");
// Checking if server accepted the username
do {
String serverReply = dis.readUTF();
if (serverReply == "FALSE"){
// disconnect from server socket TODO
System.out.println("Given Username is already in use, please provide another Username");
username = sc.nextLine();
dos.writeUTF(username);
}else {
valid = false;
}
}while (valid);
System.out.println("after while loop to check if username is unique");
sc.close();
System.out.println("client " + username + " has been connected to the server");
}
public class MonitorSharedDirectory implements Runnable {
FileInputStream fis = null;
BufferedInputStream bis = null;
#Override
public void run() {
System.out.println("inside MonitorSharedDirectory class's run method");
try{
System.out.println("inside MonitorSharedDirectory try section");
Path watchFolder = Paths.get("D:/Distributed Systems/Labs/Lab_1/client_1/shared_directory/");
WatchService watchService = FileSystems.getDefault().newWatchService();
watchFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY); //add ENTRY_MODIFY to this to monitor for file modifications
boolean valid = true;
do {
WatchKey watchKey = watchService.take();
for (WatchEvent event : watchKey.pollEvents()) {
WatchEvent.Kind kind = event.kind();
if (StandardWatchEventKinds.ENTRY_CREATE.equals(kind) || StandardWatchEventKinds.ENTRY_MODIFY.equals(kind)) {
String fileName = event.context().toString();
System.out.println("File Created:" + fileName);
int attempts = 0;
while(dis.available() == 0 && attempts < 1000)
{
attempts++;
Thread.sleep(5);
}
// sending new file to server
File myFile = new File("D:/Distributed Systems/Labs/Lab_1/client_1/shared_directory/" + fileName);
byte[] fileContents = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
dis.readFully(fileContents, 0, fileContents.length);
dos.writeUTF(myFile.getName());
dos.writeLong(fileContents.length);
dos.write(fileContents, 0, fileContents.length);
dos.flush();
System.out.println("File "+fileName+" sent to Server.");
// //fill the data into the Byte array?
// bis.read(fileContents, 0, fileContents.length);
//
// dos.writeUTF(myFile.getName());
//
// //send the length of the file to the client
// dos.writeLong(fileContents.length);
//
// System.out.println("Sending the file " + myFile + " (" + fileContents.length + " bytes)");
//
// //send the file contents to the server?
// dos.write(fileContents, 0, fileContents.length);
// dos.flush();
if (fis != null)
fis.close();
if (bis != null)
bis.close();
if (dis != null)
dis.close();
}
}
valid = watchKey.reset();
} while (valid);
}catch(Exception e){
System.out.println("Error Prem: " + e );
}finally {
//if (dos != null)
//dos.close();
try {
if (fis != null)
fis.close();
if (bis != null)
bis.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
public class receiveFileFromServer implements Runnable {
FileOutputStream fos = null;
#Override
public void run() {
System.out.println("inside receiveFileFromServer class's run method");
while (true){
try {
System.out.println("inside receiveFileFromServer try section");
// receive file from server
String fileName = dis.readUTF();
System.out.println(fileName);
fos = new FileOutputStream("D:/Distributed Systems/Labs/Lab_1/client_1/shared_directory/" + fileName);
int bytesRead = 0;
long size = dis.readLong();
byte[] buffer = new byte[(int) size];
while (size > 0 && (bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
fos.write(buffer, 0, bytesRead);
size -= bytesRead;
}
System.out.println("File " + fileName + " downloaded from server(" + size + " bytes read)");
if (fos != null)
fos.close();
} catch (Exception e) {
System.out.println("Error: " + e);
e.printStackTrace();
}
}
}
}
public void closeConnection() throws IOException {
System.out.println("inside closeConnection()");
if (dis != null)
dis.close();
if (dos != null)
dos.close();
if (clientSocket != null)
clientSocket.close();
}
}
easy approach- you could handle that by keeping a register of the files in small dB on server with file stamp and file size we call it metadata.
This way in case the file is changed in future and sent over second time with changed content, you could look up the metadata.
If the same file sent over to server, server rejects the file and it will not be propagated to other clients.
In my case I was using aws sqs, and I looked up message ids to check duplicate files.
I hope this approach helps.
I faced exact same problem while writing an inventory application with watcher and create event. rather adding thread sleep and counter in loop, I would watch the file size if it keeps changing. There is code available for this in on google. It works like charm.
[I am asking this because I have checked previous questions and none have answered my questions specific to the code here]
I am relatively new to client server coding. I have Android as client and Java server. The system at the moment works like this:: Android client selects/loads a Jpeg image from sdcard, sends int size, string text and image file to server and server sends back integer and a text file with data back to client
My problem at the moment it works perfectly (randomly) only roughly ~60% of the runs. The remainder of the time it blocks permanently and I have to restart server to continue. [Certainly, a little over half of the time, the client-server system sends and receives without a glitch, but ~40% to 45% (permanent block) failure rate is unacceptable]
When it blocks there is no crash dump, stacktrace or error to read. I have searched previous similar blocking questions and tried to close sockets and inputstream/outputstream and wrappers in different orders varying the permutations, but the success/permanent block rate remained the same
Because there is no stack trace and the randomness, I have no clue what causes the block. Except that using print statements all the server and client code the last prints that hang permanently is in the bytes receiving do-while loop in the server code
I am at a loss on what to do to solve this. I'm hoping experienced minds in this field would help solve this. Full code is below.
Java Server code
public class FileServer {
public static void main(String[] args) throws IOException {
int bytesRead;
int current = 0;
//===============================================
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
//==============================================
InetAddress IP=InetAddress.getLocalHost();
servsock = new ServerSocket(57925);
System.out.println("IP "+IP.getHostAddress()+" ***%% :"+servsock.getLocalPort());
while (true) {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
InputStream is = sock.getInputStream();
//=========================================================
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//=================== read integer from client ============
String number = br.readLine();
System.out.println("integer received from client is "+String.valueOf(number));
byte [] mybytearray = new byte [Integer.valueOf(number)];
//=================== read filename string =====================================
String filename = br.readLine();
System.out.println("integer received from client is "+filename);
//===================== read file data stream bytes ================================
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
System.out.println("1 bytesRead "+bytesRead+" mybytearray.length "+mybytearray.length);
do {
bytesRead = is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
System.out.println("2 current "+current+" bytesRead "+bytesRead);
} while(current < Integer.valueOf(number));
//============================== initialise filename ======================
FileOutputStream fos = new FileOutputStream("C:\\Server root folder\\"+filename+".jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//========================== write bytes to server HDD =======================
bos.write(mybytearray, 0 , current);
System.out.println("4 current "+current);
bos.flush();
long end = System.currentTimeMillis();
// System.out.println("AT SERVER: bytesRead "+bytesRead+" current "+current);
// bos.close();
// ======================== write to-be-rendered data to text file ======================
File pathPlusfile = new File("C:/Server root folder/"+filename+".txt");
appendToFile( pathPlusfile, "file name:: "+filename+"* *", 20999 );
/**/ //================== Send Data in text file to Client ============================================
// send file
mybytearray = new byte [(int)pathPlusfile.length()];
fis = new FileInputStream(pathPlusfile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
//===============================================
os = sock.getOutputStream();
//=========================== send integer to client ===============
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
number = Integer.toString(mybytearray.length);
String sendMessage = number + "\n";
bw.write(sendMessage);
bw.flush();
//========================== send file to client ===================
System.out.println("Sending " + filename + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
//========================= close =================================
System.out.println("number "+number);
System.out.println("Done.");
bos.close();
bw.close();
osw.close();
os.close();
// fos.close();
// bis.close();
// fis.close();
// br.close();
isr.close();
is.close();
closeFile( );
// servsock.close();
// sock.close();
}
}
BufferedReader bufferedReader = null;
String stringObjectData = "";
public int numFromFile = 0;
static BufferedWriter bufferedWriter = null;
public static void appendToFile( File myPathPlusFile, String S, int num ){
try{
bufferedWriter = new BufferedWriter(new FileWriter(myPathPlusFile, true));
bufferedWriter.append( S );
bufferedWriter.append( " " );
bufferedWriter.append( Integer.toString(num) );
bufferedWriter.newLine();
bufferedWriter.flush();
}
catch (IOException e){
e.printStackTrace();
}
}
public static void closeFile( ){
try{
bufferedWriter.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Android Client code
public class FSendfileActivity extends Activity {
private static final int SELECT_PICTURE = 1;
private Socket sock;
private String serverIP = "192.168.1.4";
private String selectedImagePath;
private ImageView img;
final static String qcd = "qcd";
String ImageDir2Client;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Button send;
//====================
public static String FILE_TO_RECEIVED=null;
String cFilename = null;
int bytesRead = -1;
int current = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fsendfile);
ImageDir2Client = Environment.getExternalStorageDirectory().getAbsolutePath();
cFilename = "fromServer000019ggg";
FILE_TO_RECEIVED = ImageDir2Client + "/client root/"+cFilename+".txt";
img = (ImageView) findViewById(R.id.ivPic);
((Button) findViewById(R.id.bBrowse)).setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult( Intent.createChooser( intent, "Select Picture" ), SELECT_PICTURE );
}
});
send = (Button) findViewById(R.id.bSend);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
new Thread(new Runnable() {
#Override
public void run() {
try {
sock = new Socket();
connection(sock, serverIP, 57925);
//=================== prepare buffer to read file ====================
File myFile = new File (selectedImagePath);
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
//=============== read file from sdcard to buffer ==========
bis.read(mybytearray,0,mybytearray.length);
//=================================================================
OutputStream os = sock.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//============================= send size integer ===================
String number = Integer.toString(mybytearray.length);
String sendMessage = number + "\n";
bw.write(sendMessage); // send size integer here
//============================= send file name =====================
String sendMessage2 = cFilename + "\n";
bw.write(sendMessage2); // send size filename here
osw.flush();
bw.flush();
//==================================================================
os.write(mybytearray,0,mybytearray.length); // send file
os.flush();
//================= client receiving data ==============================
InputStream is = sock.getInputStream();
//=================== read integer from client ==========
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
number = br.readLine();
//========================= set incoming file size=============================
mybytearray = new byte [Integer.valueOf(number)];
//========================read file bytes in chunks===============================
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead = is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(current < Integer.valueOf(number));
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bos.write(mybytearray, 0 , current);
bos.flush();
try{
bos.close();
osw.close();
os.close();
// fos.close();
// bw.close();
// br.close();
// isr.close();
bis.close();
sock.close();
// fis.close();
}
catch(Exception e){
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try{
}
catch(Exception e){
e.printStackTrace();
}
}
}
}).start();
}
});
}
public static void connection(Socket s, String serverIP, int port) {
try {
Log.v(qcd, " before connecting ****...");
s.connect(new InetSocketAddress(serverIP, port), 120000);
Log.v(qcd, " socket connection DONE!! ");
} catch (UnknownHostException e) {
e.printStackTrace();
Log.v(qcd, " Unknown host..."+e);
} catch (IOException e) {
e.printStackTrace();
Log.v(qcd, " Failed to connect... "+e);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
img.setImageURI(null);
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
TextView path = (TextView) findViewById(R.id.tvPath);
path.setText("Image Path : " + selectedImagePath);
img.setImageURI(selectedImageUri);
}
}
}
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
}
I finally fixed the code. I've had to test it over again all day long, to make sure it wasn't a false positive, so far its held on.
I hope this answer will help someone.
Originally I was using the same InputStream instance to read integer data, string data and file data at the server and the same outputStream instance to send integer data, string data and file data at the client. And at the client, they were wrapped in bufferOutputstream and bufferWritter and at server they were wrapped in bufferedInputstream and bufferedReader objects.
I think I was losing data at this point and thus the reason for the inconsistency
So to solve I had to create and use separate Outputstream instances for each data sent from the client. (note to send the file byte data - outputstream object wasn't wrapped)
Very subtle but solved it
In school we have a project where we have to send a file from server to a client. The problem we have is that when we transfer the file from the server to the client, the server shutsdown the connection. Here is our code so far:
Client:
public static void main(String argv[]) throws Exception {
int port = 8888; //default
if (argv.length
> 0) {
port = Integer.parseInt(argv[0]);
}
Socket clientSocket = new Socket("127.0.0.1", port);
PrintStream outToServer = new PrintStream(
clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
File f = new File("dictionaryPart.txt");
String serverCommand = inFromServer.readLine().toLowerCase();
while (serverCommand != null) {
System.out.println(serverCommand);
switch (serverCommand) {
case "velkommen":
outToServer.println("Hej");
break;
case "file":
f = copy(clientSocket, f);
String matches = CrackerCentralized.checkFile(f);
System.out.println(matches);
outToServer.println(matches);
break;
}
serverCommand = inFromServer.readLine().toLowerCase();
}
}
public static File copy(Socket clientSocket, File f) {
try {
int filesize = 2022386;
int bytesRead;
int currentTot = 0;
byte[] buffer = new byte[filesize];
InputStream is = clientSocket.getInputStream();
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(buffer, 0, buffer.length);
currentTot = bytesRead;
while (bytesRead != -1) {
bytesRead = is.read(buffer, currentTot, (buffer.length - currentTot));
if (bytesRead >= 0) {
currentTot += bytesRead;
}
}
bos.write(buffer, 0, currentTot);
bos.flush();
bos.close();
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
return f;
}
Server:
try {
PrintStream outToClient = new PrintStream(connection.getOutputStream());
OutputStream os = connection.getOutputStream();
BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));
outToClient.println("file");
final byte[] buffer = new byte[(int) f.length()];
input.read(buffer, 0, buffer.length);
os.write(buffer, 0, buffer.length);
os.write(-1);
os.flush();
System.out.println(connection.isClosed());
os.close();
System.out.println(connection.isClosed());
} catch (IOException ex) {
Logger.getLogger(SocketController.class.getName()).log(Level.SEVERE, null, ex);
}
I am aware of WHY the connection keeps on closing. We close the socket's output by writing
output.close();
But I don't know in what other way we must try to do this to make the server keep listening for the clients answer (match/no match), so that the server knows wether it should send more files or if the client was successful.. Is it even possible to send at file without shutting down the connection to the server? I've googled all day the last 2 days without any luck
Thanks for reading and for your help.
In order to implement what you are asking, you need to establish a communication protocol that the server and client understand. Something needs to be transmitted that says, "I'm starting to send information to you," and something that says, "I'm done sending stuff." There could be more -- such as information delimiting (e.g. Mime multipart form boundary). But at a minimum, you need the start and stop tokens.
Expanding on that: Look at the code in its simplest form: server:loop{write()} -> client:loop{read()}. Closing the stream on the server-side sends the -1 value to the client, which is usually consumed as the stop signal. If you want to maintain the connection indefinitely, and write to the client at different times, something has to be sent that says, "This transaction is complete". The following is pseudo-ish code -- freehand, not compiled.
// SERVER
private Socket socket; // initialized somewhere
private static final byte[] STOP = "</COMMS>".getBytes();
public void sendData(byte[] bytes) throws IOException{
OutputStream out = socket.getOutputStream();
if(bytes != null){
out.write(bytes,0,bytes.length);
}
out.write(STOP);
} // notice we exit the method without closing the stream.
// CLIENT
private Socket socket; // initialized somewhere
private static final byte[] STOP = "</COMMS>".getBytes();
private static final int BUFFER_SIZE = 1024 << 8;
private InputStream in;
public byte[] receiveData(){
if(in == null){
in = socket.getInputStream();
}
byte[] content;
byte[] bytes = new byte[BUFFER_SIZE];
int bytesRead;
while((bytesRead = in.read(bytes)) != -1){ // normal termination
if(receivedStop(bytes,bytesRead)){ // see if stopped
removeStopBytes(bytes,bytesRead); // get rid of the STOP bytes
content = buildContent(content,bytes,bytesRead); // transfer bytes to array
break;
}
content = buildContent(content,bytes,bytesRead); // transfer bytes to array
}
return content;
}
Again, that was freehand and not compiled or tested. I'm sure it's not fully correct but hopefully you get the gist. The server writes content but never closes the stream. The client reads the stream looking for the STOP content, building up the final content until the stop is reached.
Thanks to madConan for the reply, it gave me a good idea of how to do it. I will post my code here, so others can use it in future.
SERVER CODE
public void run() {
try {
PrintStream outToClient = new PrintStream(connection.getOutputStream());
OutputStream os = connection.getOutputStream();
BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));
outToClient.println("file");
copy(input, os, f);
System.out.println(connection.isClosed());
} catch (IOException ex) {
Logger.getLogger(SocketController.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void copy(final InputStream is, final OutputStream os, File f) throws IOException {
final byte[] stop = "stop".getBytes();
final byte[] buffer = new byte[(int) f.length()];
is.read(buffer, 0, buffer.length);
os.write(buffer, 0, buffer.length);
os.write(stop);
os.flush();
}
CLIENT CODE
public static File recieveData(Socket clientSocket, File f) {
try {
InputStream in = clientSocket.getInputStream();
FileOutputStream output = new FileOutputStream(f);
byte[] content;
byte[] bytes = new byte[1024 << 8];
int bytesRead;
while (true) {
if (recieveStop(f)) {
removeStop(f);
break;
}
bytesRead = in.read(bytes);
output.write(bytes, 0, bytesRead);
}
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
return f;
}
public static boolean recieveStop(File f) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(f));
String currentLine;
String lastLine = "";
while ((currentLine = br.readLine()) != null) {
lastLine = currentLine;
}
if (lastLine.equals("stop")) {
return true;
}
} catch (FileNotFoundException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
return false;
}
public static void removeStop(File f) {
try {
RandomAccessFile raFile = new RandomAccessFile(f, "rw");
long length = raFile.length();
raFile.setLength(length - 4);
raFile.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Master_Slave_Sockets_Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
Hope this will help others with the same problem.
I've tried to write a server and a client in java, to transfer a file. but the received file is weird and look like it's filled with strange bytes and it won't open with any application, however its size is exactly same as the source file.
I don't know where the problem is! is it about encoding?
Server-side:
import java.net.*;
import java.io.*;
public class MyServer {
public static void main(String[] args) {
char sp = File.separatorChar;
String home = System.getProperty("user.home");
try {
ServerSocket server = new ServerSocket(5776);
while (true){
Socket connection = server.accept();
try {
String FileName=home+sp+"33.jpg";
File inputFile = new File(FileName);
FileInputStream Fin = new FileInputStream(inputFile);
long fileLength = inputFile.length();
byte[] bt= new byte[(int) fileLength];
DataOutputStream Oout = new DataOutputStream(connection.getOutputStream());
Oout.writeLong(fileLength);
Oout.write(bt);
Oout.flush();
Oout.close();
connection.close();
} catch (IOException ex) {}
finally {
try {
if(connection!= null) connection.close();
} catch (IOException e) {}
}
}
} catch (IOException e) {
System.err.println("There is a server on port 5776");
}
}
}
Client-side:
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) {
byte[] IP={(byte)192,(byte)168,1,7};
char sp = File.separatorChar;
String home = System.getProperty("user.home");
String SharingPathString = home+sp+"File Sharing";
String FileName = SharingPathString+sp+"file.jpg";
try {
InetAddress add = InetAddress.getByAddress(IP);
Socket theSocket= new Socket("Shayan-8",5776);
DataInputStream in= new DataInputStream(theSocket.getInputStream());
final long FileLength = in.readLong();
System.out.println("FileLength: "+FileLength);
File SharingPath = new File(SharingPathString);
if(!SharingPath.exists())
SharingPath.mkdir();
File outputFile = new File(FileName);
if(outputFile.exists())
outputFile.delete();
//outputFile.createNewFile();
FileOutputStream Fos = new FileOutputStream(FileName);
DataOutputStream dos = new DataOutputStream(Fos);
byte[] buffer = new byte[100];
int count=0;
long current=0;
while(current < FileLength && (count=in.read(buffer,0,(int)Math.min(FileLength-current, buffer.length)))!=-1)
{Fos.write(buffer, 0, count);
current+=count;
}
// while((count=in.read())!=-1)
// dos.write(count);
dos.close();
Fos.close();
} catch (UnknownHostException uhe) {
System.err.println(uhe);
} catch (IOException e) {
System.err.println(e);
}
}
}
You haven't read anything into bt[]. So you are writing the correct number of null bytes.