Why server-side shows a null pointer exception (in client server application)? - java

In my client server application, client sends some commands and the server gives the results back. Now the problem is when the client tries to download a file from the server, by using GET filename command. The program works fine, even it can doesnload the file correctly, but the problem is in the server side's command prompt there is always a null pointer exception error remains. And it happens immediately after I enter the GET command. Error:
Second issue appears when I remove fis.close(); line in serverside. It shows another trace error in the server side: Error:
This is the complete project I am working on:
ClientSide:
package clientside;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ClientSide {
private static Socket socket;
private static PrintWriter outputToServer;
private static BufferedReader inputFromServer;
private static InputStream is;
private static FileOutputStream fos;
private static final int PORT = 8000;
private static final String SERVER = "85.197.159.45";
boolean Connected;
DataInputStream serverInput;
public static void main(String[] args) throws InterruptedException {
String server = "localhost";
int port = PORT;
if (args.length >= 1) {
server = args[0];
}
if (args.length >= 2) {
port = Integer.parseInt(args[1]);
}
new ClientSide(server, port);
}
public ClientSide(String server, int port) {
try {
socket = new Socket(server, port);
serverInput = new DataInputStream(socket.getInputStream());
outputToServer = new PrintWriter(socket.getOutputStream(), true);
inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Client is connected! ");
Connected = true;
String line = null;
Scanner sc = new Scanner(System.in);
System.out.print("Type command: ");
while (sc.hasNextLine()) {
String request = sc.nextLine();
if (request.startsWith("exit")) {
outputToServer.println(request);
System.out.println("Application exited!");
//outputToServer.flush();
break;
} else if (request.startsWith("pwd")) {
outputToServer.println(request);
outputToServer.flush();
} else if (request.startsWith("list")) {
outputToServer.println(request);
outputToServer.flush();
} else if (request.startsWith("GET")) {
System.out.print("\r\n");
outputToServer.println(request);
outputToServer.flush();
}
while (Connected) {
line = inputFromServer.readLine();
System.out.println(line);
if (line.isEmpty()) {
Connected = false;
if (inputFromServer.ready()) {
System.out.println(inputFromServer.readLine());
}
}
if (line.startsWith("Status 400")) {
while (!(line = inputFromServer.readLine()).isEmpty()) {
System.out.println(line);
}
break;
}
if (request.startsWith("GET")) {
File file = new File(request.substring(4));
is = socket.getInputStream();
fos = new FileOutputStream(file);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
serverInput = new DataInputStream(socket.getInputStream());
//int bytesReceived = 0;
byte[] inputByte = new byte[4000];
int length;
while ((length = serverInput.read(inputByte, 0, inputByte.length)) > 0) {
fos.write(inputByte, 0, length);
}
/*
while ((bytesReceived = is.read(buffer)) >=0) {
//while ((bytesReceived = is.read(buffer))>=buffer) {
fos.write(buffer, 0, bytesReceived);
}
*/
request = "";
fos.close();
is.close();
}
}
System.out.print("\nType command: ");
Connected = true;
}
outputToServer.close();
inputFromServer.close();
socket.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
ServerSide:
package serverside;
import java.io.*;
import java.net.*;
import java.util.Arrays;
public class ServerSide {
private BufferedReader inputFromClient;
private PrintWriter outputToClient;
private FileInputStream fis;
private OutputStream os;
private static final int PORT = 8000;
private ServerSocket serverSocket;
private Socket socket;
public static void main(String[] args) {
int port = PORT;
if (args.length == 1) {
port = Integer.parseInt(args[0]);
}
new ServerSide(port);
}
private boolean fileExists(File[] files, String filename) {
boolean exists = false;
for (File file : files) {
if (filename.equals(file.getName())) {
exists = true;
}
}
return exists;
}
public ServerSide(int port) {
// create a server socket
try {
serverSocket = new ServerSocket(port);
} catch (IOException ex) {
System.out.println("Error in server socket creation.");
System.exit(1);
}
while (true) {
try {
socket = serverSocket.accept();
os = socket.getOutputStream();
outputToClient = new PrintWriter(socket.getOutputStream());
inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String request = inputFromClient.readLine();
if (!request.startsWith("exit") && !request.startsWith("pwd") && !request.startsWith("list") && !request.startsWith("GET")) {
outputToClient.println("Wrong request\r\n"
+ "\r\n");
} else if (request.startsWith("exit")) {
break;
} else if (request.startsWith("pwd")) {
File file = new File(System.getProperty("user.dir"));
outputToClient.print("Status OK\r\n"
+ "Lines 1\r\n"
+ "\r\n"
+ "Working dir: " + file.getName() + "\r\n");
} else if (request.startsWith("list")) {
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
outputToClient.print("Status OK\r\n"
+ "Files " + files.length + "\r\n"
+ "\r\n"
+ Arrays.toString(files).substring(1, Arrays.toString(files).length() - 1) + "\r\n");
} else if (request.startsWith("GET")) {
String filename = request.substring(4);
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
if (fileExists(files, filename)) {
file = new File(filename);
int fileSize = (int) file.length();
outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n",
fileSize, filename);
outputToClient.flush();
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[(1 << 7) - 1];
int bytesRead = 0;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
os.close();
fis.close();//NPE is happening here.
} else {
outputToClient.print("Status 400\r\n"
+ "File " + filename + " not found\r\n"
+ "\r\n");
outputToClient.flush();
}
}
outputToClient.flush();
}
} catch (IOException e) {
System.err.println(e);
}
finally{
os.close();
}
}
}
}
UPDATE: Even if I remove the fis.close(); line from the server side, it shows java.net.SocketException: socket closed error.

The original problem is that you are using a try-with-resources block with an assigned variable with the same name as one of your class member variables. Removing the following line will remove the NPE:
fis.close();
The SocketException is being caused by the line:
os.close();
According to the documentation of Socket::getOutputStream:
Closing the returned OutputStream will close the associated socket.
Therefore, moving the line os = socket.getOutputStream(); to just below the line socket = serverSocket.accept(); line, and also moving os.close() to a finally block after your final catch block should solve this issue.

The socket represented by fis is null.
To correct, use this:
if (fis != null) fis.close;

try (FileInputStream fis = new FileInputStream(file))
In this line you are creating a new FileInputStream and using it, and it is not your FileInputStream field, declared before. This fis exists only on the "try" block. When you try to close your fis os.close(); you are trying to close your fis field, not the fis declared in the try.
Use this, instead:
try (fis = new FileInputStream(file)). With this you are instantiating a new FileInputStream in your field, not in a new variable.

Related

Java socket based file transfer application client runs when being debugged but fails when run normally

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.

Java socket is stuck on readUTF()

I'm trying to transfer files over a socket in Java, my current approach for the server is:
Create new Thread
Thread sends file name using dos.writeUTF()
Thread sends file size using dos.writeLong()
Thread sends file using dos.write()
Where each Thread represents a client and dos is an instance of DataOutputStream.
Now, on the client I'm doing the same thing but reading instead of writing:
Read file name using dis.readUTF()
Read file size using dis.readLong()
Read file using dis.read()
Where dis is an instance of DataInputStream.
The problem is: when sending one file, everything goes right, but when I try to send 3 files, one after another, it looks like the server is writing everything correctly to the stream as expected but the client (After the first file, which means this starts happening from the second file) is stuck on dis.readUTF() and can't move on.
I've tried fixing this for days but can't get anything to work.
Here's the source code:
SERVER:
Main.java
public class Main {
public static void main(String[] args) {
boolean boolDebug = true;//TODO REMOVE THIS!!
ServerSocket serverSock = null;
List<Socket> clientSocks;
List<ClientThread> clientThreads;
try {
serverSock = new ServerSocket(9090);
} catch(Exception e){
e.printStackTrace();
}
clientSocks = new ArrayList<>();
clientThreads = new ArrayList<>();
ServerSocket finalServerSock = serverSock;
System.out.println();
System.out.println("Listening for incoming connections\n");
new Thread(){
#Override
public void run() {
super.run();
while (true) {
try {
Socket newSock = finalServerSock.accept();
clientSocks.add(newSock); //FIXME Remove sockets when closed
Thread thread = new ClientThread(newSock, usr, psw);
thread.start();
clientThreads.add((ClientThread)thread);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
}
ClientThread.java
public class ClientThread extends Thread {
private Socket socket;
private DataInputStream inStream;
private DataOutputStream outStream;
private String dbUser;
private String dbPassword;
public ClientThread(Socket socket, String DbUser, String DbPass) {
this.socket = socket;
this.dbUser = DbUser;
this.dbPassword = DbPass;
}
#Override
public void run() {
try {
inStream = new DataInputStream(socket.getInputStream());
outStream = new DataOutputStream(socket.getOutputStream());
sendFile("a.txt");
sendFile("b.txt");
sendFile("c.txt");
} catch (Exception e) {
e.printStackTrace();
}
}
void sendFile(String file){
try {
File f = new File(file);
outStream.writeUTF(file);
outStream.writeLong(f.length());
FileInputStream fis = new FileInputStream(f);
byte[] buffer = new byte[4096];
while (fis.read(buffer) > 0) {
outStream.write(buffer);
}
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
int getSize(byte[] buffer,long remaining){
try {
return Math.toIntExact(Math.min(((long) buffer.length), remaining));
}catch(ArithmeticException e){
return 4096;
}
}
}
CLIENT:
Main.java
class Main {
static int getSize(byte[] buffer, long remaining) {
try {
return Math.toIntExact(Math.min(((long) buffer.length), remaining));
} catch (ArithmeticException e) {
return 4096;
}
}
static void saveFile(Socket clientSock,DataInputStream dis) throws IOException {
String fileName = dis.readUTF();
File f = new File(fileName);
FileOutputStream fos = new FileOutputStream(f);
byte[] buffer = new byte[4096];
long filesize = dis.readLong();
int read = 0;
int totalRead = 0;
long remaining = filesize;
while ((read = dis.read(buffer, 0, getSize(buffer, remaining))) > 0) {
totalRead += read;
remaining -= read;
System.out.println("read " + totalRead + " bytes.");
fos.write(buffer, 0, read);
}
fos.close();
}
public static void main(String[] args) throws Exception {
Socket sock = new Socket("192.168.2.17", 9090);
DataInputStream dis = new DataInputStream(sock.getInputStream());
saveFile(sock,dis);
saveFile(sock,dis);
saveFile(sock,dis);
}
}
Many thanks in advance, looking forward to fix this :(
Fixed by changing
while (fis.read(buffer) > 0) {
outStream.write(buffer);
}
to
int count;
while ((count = fis.read(buffer)) > 0) {
outStream.write(buffer, 0, count);
}
Inside ClientThread.java on the server side

FileoutputStream doesn't output any string after the empty line (Line break) [duplicate]

This question already has answers here:
Why fileOutputStream can't output any string after an empty line (or a line break) in client-server application?
(2 answers)
Closed 7 years ago.
In my client-server application, when I try to download a file from the serverSide, the file gets downloaded; but the header information such as some additional text with line break can't be read. As you can see in my Server class this following information is supposed to be printed out in the client side.
outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n",
fileSize, filename);
But it doesn't. Only the fisrt string (Status OK) before the \r\n gets printed, not any string after \r\n.
How can I fix it?
My complete code:
ServerSide:
public class ServerSide {
private BufferedReader inputFromClient;
private PrintWriter outputToClient;
private FileInputStream fis;
private OutputStream os;
private static final int PORT = 8000;
private ServerSocket serverSocket;
private Socket socket;
public static void main(String[] args) {
int port = PORT;
if (args.length == 1) {
port = Integer.parseInt(args[0]);
}
new ServerSide(port);
}
private boolean fileExists(File[] files, String filename) {
boolean exists = false;
for (File file : files) {
if (filename.equals(file.getName())) {
exists = true;
}
}
return exists;
}
public ServerSide(int port) {
// create a server socket
try {
serverSocket = new ServerSocket(port);
} catch (IOException ex) {
System.out.println("Error in server socket creation.");
System.exit(1);
}
while (true) {
try {
socket = serverSocket.accept();
outputToClient = new PrintWriter(socket.getOutputStream());
inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String request = inputFromClient.readLine();
if (!request.startsWith("exit") && !request.startsWith("pwd") && !request.startsWith("list") && !request.startsWith("GET")) {
outputToClient.println("Wrong request\r\n"
+ "\r\n");
} else if (request.startsWith("exit")) {
break;
} else if (request.startsWith("pwd")) {
File file = new File(System.getProperty("user.dir"));
outputToClient.print("Status OK\r\n"
+ "Lines 1\r\n"
+ "\r\n"
+ "Working dir: " + file.getName() + "\r\n");
} else if (request.startsWith("list")) {
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
outputToClient.print("Status OK\r\n"
+ "Files " + files.length + "\r\n"
+ "\r\n"
+ Arrays.toString(files).substring(1, Arrays.toString(files).length() - 1) + "\r\n");
} else if (request.startsWith("GET")) {
String filename = request.substring(4);
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
if (fileExists(files, filename)) {
file = new File(filename);
int fileSize = (int) file.length();
outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n",
fileSize, filename);
outputToClient.flush();
try (FileInputStream fis = new FileInputStream(file)) {
os = socket.getOutputStream();
byte[] buffer = new byte[(1 << 7) - 1];
int bytesRead = 0;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
//os.close();
// fis.close();
} else {
outputToClient.print("Status 400\r\n"
+ "File " + filename + " not found\r\n"
+ "\r\n");
outputToClient.flush();
}
}
outputToClient.flush();
}
} catch (IOException e) {
System.err.println(e);
}
}
}
}
ClientSide:
public class ClientSide {
private static Socket socket;
private static PrintWriter outputToServer;
private static BufferedReader inputFromServer;
private static InputStream is;
private static FileOutputStream fos;
private static final int PORT = 8000;
private static final String SERVER = "85.197.159.45";
boolean Connected;
DataInputStream serverInput;
public static void main(String[] args) throws InterruptedException {
String server = "localhost";
int port = PORT;
if (args.length >= 1) {
server = args[0];
}
if (args.length >= 2) {
port = Integer.parseInt(args[1]);
}
new ClientSide(server, port);
}
public ClientSide(String server, int port) {
try {
socket = new Socket(server, port);
serverInput = new DataInputStream(socket.getInputStream());
outputToServer = new PrintWriter(socket.getOutputStream(), true);
inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Client is connected! ");
Connected = true;
String line = null;
Scanner sc = new Scanner(System.in);
System.out.print("Type command: ");
while (sc.hasNextLine()) {
String request = sc.nextLine();
if (request.startsWith("exit")) {
outputToServer.println(request);
System.out.println("Application exited!");
//outputToServer.flush();
break;
} else if (request.startsWith("pwd")) {
outputToServer.println(request);
outputToServer.flush();
} else if (request.startsWith("list")) {
outputToServer.println(request);
outputToServer.flush();
} else if (request.startsWith("GET")) {
System.out.print("\r\n");
outputToServer.println(request);
outputToServer.flush();
}
while (Connected) {
line = inputFromServer.readLine();
System.out.println(line);
if (line.isEmpty()) {
Connected = false;
if (inputFromServer.ready()) {
System.out.println(inputFromServer.readLine());
}
}
if (line.startsWith("Status 400")) {
while (!(line = inputFromServer.readLine()).isEmpty()) {
System.out.println(line);
}
break;
}
if (request.startsWith("GET")) {
File file = new File(request.substring(4));
is = socket.getInputStream();
fos = new FileOutputStream(file);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
serverInput = new DataInputStream(socket.getInputStream());
//int bytesReceived = 0;
byte[] inputByte = new byte[4000];
int length;
while ((length = serverInput.read(inputByte, 0, inputByte.length)) > 0) {
fos.write(inputByte, 0, length);
}
request = "";
fos.close();
}
}
System.out.print("\nType command: ");
Connected = true;
}
outputToServer.close();
inputFromServer.close();
socket.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
You should close the output stream outputToClient.close() after final outputToClient.flush()

How to transfer a zip file through socket programming in java?

I am new to socket programming. I did a simple program to transfer zip files but that is only creating an empty zip and doesn't transfer any files. Can you help me please?
Client.java
package fileTransfer;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class SimpleClient {
public final static int SOCKET_PORT = 13267;
public final static String SERVER = "00.200.00.00";
public final static String
FILE_TO_RECEIVED = "D:/Projects/Transferred.zip";
public final static int FILE_SIZE = 6022386;
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {
sock = new Socket(SERVER, SOCKET_PORT);
System.out.println("Connecting...");
// receive file
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
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 < FILE_SIZE);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED + " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
}
}
}
Server.java
package fileTransfer;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer {
public final static int SOCKET_PORT = 13267;
public final static String FILE_TO_SEND = "C:/Users/Public/Pictures/Sample Pictures.zip";
public static void main (String [] args ) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
try {
servsock = new ServerSocket(SOCKET_PORT);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// send file
File myFile = new File (FILE_TO_SEND);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
finally {
if (bis != null) bis.close();
if (os != null) os.close();
if (sock!=null) sock.close();
}
}
}
finally {
if (servsock != null) servsock.close();
}
}
}
Kindly help me fix this!!!
Try to read file in such way on client side:
Socket s = servsock.accept();
InputStream in = s.getInputStream();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("YOUR_FILE"));
int c=0;
byte[] buff=new byte[2048];
while((c=in.read(buff))>0){ // read something from inputstream into buffer
// if something was read
bos.write(buff, 0, c);
}
in.close();
bos.close();
Do the same on the server side. Your InputStream will be a file and output will be a socket. Its robust way to copy streams.
I was finally able to transfer zip files through the socket. Please find the code below.
If anyone feels that it could be made much better. Please let me know:
Client.java
public class Client {
public final static int SOCKET_PORT = 13267;
public final static String SERVER = "00.200.00.00";
public final static String
FILE_TO_RECEIVED = "D:/Projects/Transferred.zip";
public final static int FILE_SIZE = 5830740;
public static void main(String args[]) {
int bytesRead;
int current = 0;
PrintWriter pwr=null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
BufferedReader br = null;
Socket sock = null;
String filesize= null, s=null;
try {
sock = connectToServer(SERVER, SOCKET_PORT);
System.out.println("Connecting...");
br= new BufferedReader(new InputStreamReader(sock.getInputStream()));
pwr = new PrintWriter(sock.getOutputStream());
String input=null, output = "SENDZIP";
while((input = br.readLine()) != null){
System.out.println("INPUT is "+input);
if (input.contains("SENTZIP")){
byte [] mybytearray = new byte [Integer.parseInt(s)];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
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 < FILE_SIZE);
bos.write(mybytearray, 0 , current);
bos.flush();
ZipFile file = new ZipFile(FILE_TO_RECEIVED) ;
System.out.println(file.size()+ " zip files are received in the client");
output = "Received"+file.size();
System.out.println(input+" when output is "+output);
pwr.println(output);
}
pwr.flush();
}
// receive file
#SuppressWarnings("resource")
ZipFile file = new ZipFile(FILE_TO_RECEIVED) ;
System.out.println(file.size()+ "in client");
System.out.println("File " + FILE_TO_RECEIVED +" has no of files "+file.size() + " downloaded (" + current + " bytes read)");
} catch (IOException e) {
System.out.println("Exception in Input Stream in Client");
e.printStackTrace();
}
finally {
if (fos != null){
try {
fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
} catch (IOException e) {
System.out.println("Exception in closing FileOutputStream or BufferedReader or Socket");
e.printStackTrace();
}
}
}
}
public static Socket connectToServer(String server2, int socketPort) {
Socket sock = null;
try {
sock = new Socket(server2, socketPort);
} catch (IOException e) {
System.out.println("Exception in establishing connection with server");
e.printStackTrace();
}
return sock;
}
}
Server.java
public class Server
{
public final static int SOCKET_PORT = 13267;
public final static String FILE_TO_SEND = "C:/Public/Pictures/Sample Pictures.zip";
public static void main (String [] args ) throws IOException {
FileInputStream fis;
BufferedInputStream bis = null;
BufferedReader br;
OutputStream os = null;
ServerSocket servsock = null;
PrintWriter pw;
Socket sock = null;
try {
servsock = new ServerSocket(SOCKET_PORT);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
pw = new PrintWriter(sock.getOutputStream(), true);
pw.println("SendZip");
br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
File myFile = new File (FILE_TO_SEND);
Integer i = (int) (long) myFile.getTotalSpace();
String input, output;
while ((input = br.readLine()) != null) {
System.out.println("in while loop");
if(input.equals("SENDZIP"))
{
output = "SENTZIP";
pw.println(output);
System.out.println(input+ " is the input and output is "+output);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
}
}
pw.flush();
System.out.println("Done.");
}
finally {
if (bis != null) bis.close();
if (os != null) os.close();
if (sock!=null) sock.close();
}
}
}
finally {
if (servsock != null) servsock.close();
}
}
}

Java streams with EOFException

I wrote some client - server program, that shares data but at server side i got EOFException after reciving data. I tried to fix it on my own but it is hard to find own errors.
The error is caused by this line: Message command =(Message) serInputStream.readObject();
Here is some output from server:
java.io.EOFException
at Java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2577)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1315)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at transfer.Serwerus.run(Serwerus.java:42)
Server code:
import java.io.*;
import java.net.*;
public class Serwerus implements Runnable
{
public InputStream is;
public FileOutputStream fos;
public BufferedOutputStream bos;
public ObjectOutputStream serOutputStream;
public ObjectInputStream serInputStream;
ServerSocket socket;
private String clientMessage, clientFileName;
private int clientFileSize;
public Serwerus()
{
try
{
socket = new ServerSocket(6060);
System.out.println("Server started....");
}
catch(IOException e)
{
System.err.println("Error: " + e);
e.printStackTrace();
}
}
#Override
public void run()
{
try
{
Socket sock = socket.accept();
System.out.println("Client accepted");
serOutputStream = new ObjectOutputStream(sock.getOutputStream());
serInputStream = new ObjectInputStream(sock.getInputStream());
while (true)
{
Message command =(Message) serInputStream.readObject();
System.out.println("after readObject");
if (command.getCommand().startsWith("FileU"))
{
System.out.println("Name = " + command.getfileName() + ", size= " + command.getfileSize());
serOutputStream.writeObject(new Message("Bring", "", 0));
//ReciveData(socket, command.getfileName(), command.getfileSize());
}
else if(command.getCommand().startsWith("Wait"))
{
System.out.println("hohoho");
ReciveData(sock, command.getfileName(), command.getfileSize());
}
else if(command.getCommand().startsWith("Quit"))
{
System.exit(1);
}
else
{
System.out.println("Unknow");
}
}
}
catch(ClassNotFoundException | IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
serInputStream.close();
serOutputStream.close();
socket.close();
}
catch (IOException e)
{
System.err.println("Fallen on closing socket.\n Error: " + e);
}
}
}
public void SendData(Socket sock, String filePath) throws Exception
{
File myFile = new File (filePath);
System.out.println("File name = " + myFile.getName() + " File len = " + (int)myFile.length());
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
sock.close();
System.out.println("Sending finished");
}
public void ReciveData(Socket sock, String filePath, int fileSize)
{
System.out.println("Recive in progress, filesize = " + fileSize);
int bytesRead = 0, current = 0;
byte[] array = new byte[fileSize];
try
{
is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream(filePath);
bos = new BufferedOutputStream(fos);
do
{
System.out.println(bytesRead);
bytesRead = is.read(array);
current += bytesRead;
}
while(bytesRead > -1);
bos.write(array, 0 , current);
bos.flush();
bos.close();
fos.close();
// sock.close();
System.out.println("Reciveing finished");
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
public static void main (String [] args ) throws IOException
{
new Thread(new Serwerus()).start();
}
}
Client code:
import java.io.*;
import java.net.*;
public class Clientus implements Runnable
{
InputStream is;
FileOutputStream fos;
BufferedOutputStream bos;
ObjectOutputStream cliOutputStream;
ObjectInputStream cliInputStream;
Socket socket;
File actFile;
private String serverMessage, serverFileName;
private int serverFileSize;
public Clientus()
{
try
{
socket = new Socket("localhost", 6060);
cliOutputStream = new ObjectOutputStream(socket.getOutputStream());
cliInputStream = new ObjectInputStream(socket.getInputStream());
File file = new File(<filepath>);
actFile = file;
}
catch (Exception e)
{
System.err.println("Error: " + e);
e.printStackTrace();
}
}
#Override
public void run()
{
try
{
cliOutputStream.writeObject(new Message("FileU", actFile.getPath(), (int) actFile.length()));
cliOutputStream.flush();
//while (true)
//{
Message command =(Message) cliInputStream.readObject();
if (command.getCommand().startsWith("File"))
{
String name = command.getfileName();
int size = command.getfileSize();
System.out.println("Name = " + command.getfileName() + ", size= " + command.getfileSize());
if(size != 0 && !"".equals(name))
{
//ReciveData(socket, 0);
}
}
else if(command.getCommand().startsWith("Bring"))
{
cliOutputStream.writeObject(new Message("Wait", "D:\\KP2\\Serwer\\dupa.txt",(int) actFile.length()));
cliOutputStream.flush();
try
{
SendData(socket, actFile.getPath());
//this.socket.close();
}
catch (Exception ex)
{
System.err.println("Error with: SendData()");
}
}
else if(command.getCommand().startsWith("Quit"))
{
System.exit(1);
}
else
{
System.out.println("Command unknown");
}
//}
}
catch(ClassNotFoundException | IOException ex)
{
ex.printStackTrace();
}
finally
{
try
{
socket.close();
cliOutputStream.close();
cliInputStream.close();
}
catch (IOException e)
{
System.err.println("Fallen on closing socket.\n Error: " + e);
}
}
}
public void SendData(Socket sock, String filePath) throws Exception
{
byte [] mybytearray = new byte [(int) new File(filePath).length()];
FileInputStream fis = new FileInputStream(filePath);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
fis.close();
bis.close();
os.close();
System.out.println("Sending finished");
}
public void ReciveData(Socket sock, String fileName, int fileSize)
{
int bytesRead, current = 0;
byte[] array = new byte[fileSize+1];
try
{
is = sock.getInputStream();
fos = new FileOutputStream(<file_path>);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(array,0,array.length);
current = bytesRead;
do
{
bytesRead = is.read(array, current, (array.length - current));
if(bytesRead >= 0)
current += bytesRead;
}
while(bytesRead > -1);
bos.write(array, 0 , current);
bos.flush();
long end = System.currentTimeMillis();
//System.out.println("Send time: " + (end - start));
bos.close();
sock.close();
System.out.println("Reciveing finished");
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
public static void main (String [] args ) throws IOException
{
new Thread(new Clientus()).start();
}
}
Can anyone help?
Your client may be disconnected after sending data and because your server is waiting for more data, the EOFException will occurr.
To fix this problem, you can add try-catch block to catching this exception when the client disconnects.
You are using both the ObjectOutputStream and the socket's own OutputStream to send data on, and you are getting out of sync. When you send the raw data directly over the socket you aren't sending the length first, so the receiver doesn't know how many bytes belong to this transmission. In fact it just reads everything until EOS, so next time you call ObjectInputStream.readObject() it naturally gets an EOFException. To fix this:
Use the ObjectInputStream and ObjectOutputStream for everything.
Before sending the file, send its length, via writeLong().
At the receiver, when receiving the file, first get its length, via readLong(), then read exactly that many bytes from the ObjectInputStream and copy them to the file.

Categories

Resources