i'm new to java. I'm trying to create a simple java file server from where the clients can request for a file and download it. basically when a client requests for a file it will simply will be written from server's folder to client folder. When i run my code it does not show any error but the file that client requested is not written to it's folder either.
my client side code:
public void download(Socket s) throws Exception {
DataInputStream din=new DataInputStream(s.getInputStream());
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedReader con = new BufferedReader(new InputStreamReader(System.in));
PrintWriter w = new PrintWriter(s.getOutputStream(), true);
System.out.print("Enter File Name :");
String request = con.readLine();
w.println(request);
String msg = r.readLine();
if (msg.startsWith("ERROR")) {
System.out.println("File not found on Server ...");
return;
} else if (msg.startsWith("FOUND")) {
System.out.println("Receiving File ...");
File f = new File(request);
if (f.exists()) {
String Option;
System.out.println("File Already Exists. Want to OverWrite (Y/N) ?");
Option = con.readLine();
if (Option == "N") {
dout.flush();
return;
}
}
FileOutputStream fileout = new FileOutputStream(f);
int ch;
String temp;
do {
temp = din.readLine();
ch = Integer.parseInt(temp);
if (ch != -1) {
fileout.write(ch);
}
} while (ch != -1);
fileout.close();
System.out.println(din.readLine());
}
}
The server side:
public class Fileagent extends Thread {
Socket client;
DataInputStream din;
DataOutputStream dout;
ServerSocket soc;
PrintWriter w;
BufferedReader r;
public Fileagent(Socket soc) {
try {
client = soc;
din = new DataInputStream(client.getInputStream());
dout = new DataOutputStream(client.getOutputStream());
w = new PrintWriter(client.getOutputStream(), true);
r = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedReader con = new BufferedReader(new InputStreamReader(System.in));
System.out.println("FTP Client Connected ...");
start();
} catch (Exception ex) {
}
}
public void upload() throws Exception {
w.println("SEnding.....");
String file = r.readLine();
File f = new File(file);
if (!f.exists()) {
w.println("ERROR");
return;
} else {
w.println("FOUND");
FileInputStream fin = new FileInputStream(f);
int ch;
do {
ch = fin.read();
w.println(String.valueOf(ch));
} while (ch != -1);
fin.close();
}
I'm trying to send simple text files but the files is not being send to clients.
Thanks in advance.
I suspect the problem is that you are not flushing your PrintWriter after sending the request from the client to the server:
w.println(request);
w.flush();
You seem to be using a PrintWriter on the server side as well. Make sure to call w.flush() or w.close() when you are done sending stuff over.
Also, I assume you realize that this is an extremely inefficient way to send the file over.
It looks like your problem stems from this
String request=con.readLine();
You're always reading from this con object. But you're passing in a Socket s to the method.
There are other problems, such as what Gray mentioned, and also that you're writing each character on its own line, but those are just messed up formatting; they shouldn't prevent you from getting a file at all...
Related
I am trying to create a Client-Server model of file transferring in Java in which the client will read a file and send the data to the server and the server will receive the data and write it to a file. I had already seen this post, but it deals with C.
I wrote a simple algorithm which would just send the file as soon it connects to the server.
This is the code for the client:
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String args[]) {
try {
Socket s = new Socket(args[0], Integer.parseInt(args[1]));
System.out.println("Connected to " + s.getRemoteSocketAddress());
DataInputStream din = new DataInputStream(s.getInputStream());
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
File file = new File(args[2]);
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
int no_of_bytes = 0;
while ((no_of_bytes = fis.read(buffer)) != -1) {
dout.write(buffer, 0, no_of_bytes);
}
} catch (Exception e) {
System.err.println(e.getLocalizedMessage());
}
}
}
This is the code for the server:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String args[]) {
try {
ServerSocket ss = new ServerSocket(Integer.parseInt(args[0]));
Socket s = ss.accept();
System.out.println("Connected to " + s.getRemoteSocketAddress());
DataInputStream din = new DataInputStream(s.getInputStream());
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
File new_file = new File("/home/Puspam/Videos/received.png");
new_file.createNewFile();
BufferedWriter bw = new BufferedWriter(new FileWriter(new_file));
int a;
while ((a = din.read()) != -1) {
bw.write((char) a);
}
din.close();
bw.flush();
} catch (Exception e) {
System.err.println(e.getLocalizedMessage());
}
}
}
After running the two programs with an image file for the experiment, I could find that the file has not been transferred properly. When I try to open the received file, the image viewer software in my PC shows an error that it is not a valid image file. Also, I could see that the received file is a bit larger than the original one.
What mistake am I doing here?
I've had this kinda thing before. Try to use the same type of Input/Output Stream on both ends. Like, BufferedReader to BufferedWriter, etc. You're using a FileInputStream in conjunction with a BufferedWriter. Also, you may need to flush the BufferedWriter in every iteration of your for loop.
I am new to socket programming. I have to write a program where client accepts filename from a user and sends it to the server. The server reads corresponding file and sends its content back to client. Now my problem is server program freezes on 'String file = br.readLine()'. When I terminate my client program, further lines of server code get executed. If I comment out while loop at the end of my client code, server code works perfectly fine(it prints data to standard output). Can you tell what could be wrong with my code?
Server Code:
public class SocketServer {
public static void main(String[] args) throws Exception{
System.out.println("Server is started.");
ServerSocket ss = new ServerSocket(9999);
System.out.println("Server is waiting for a client.");
Socket server = ss.accept();
System.out.println("Client is connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(server.getInputStream()));
String file = br.readLine();
System.out.println("Requested file is: " + file);
OutputStreamWriter os = new OutputStreamWriter(server.getOutputStream());
PrintWriter writer = new PrintWriter(os);
BufferedReader fr = new BufferedReader(new FileReader(file));
String line;
while((line = fr.readLine()) != null) {
writer.write(line);
writer.flush();
System.out.println(line);
}
}
}
Client Code:
public class SocketClient {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
Socket client = new Socket("localhost", 9999);
OutputStreamWriter os = new OutputStreamWriter(client.getOutputStream());
PrintWriter writer = new PrintWriter(os);
System.out.print("Enter filename: ");
String file = in.nextLine();
writer.write(file);
writer.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("Content of " + file + ":");
String str;
while((str = br.readLine()) != null) {
System.out.print(str);
}
System.out.println("File transfer is complete.");
}
}
br.readLine(); will wait for input till it finds a new-line .
writer.write(file); You are writing file name without a new-line.
So in order to make it work either write a newline char at client or read it char by char at server.
Hope this helps.
I wrote a simple socket tutorial about sending/receive messages between client and server. I used DataOutputStream to write the string in stream but server couldn't read it if I used BufferedReader
If I use PrintWriter to write(client side), it works.
What's wrong here? Tks so much.
1. Client:
client = new Socket("localhost", 1982);
DataOutputStream opStr = new DataOutputStream(client.getOutputStream());
//pw = new PrintWriter(client.getOutputStream(), true);
//pw.println("Hello, is there anybody out there?");// Can be read by BufferedReader
opStr.writeUTF("Hello, anyone there?");
opStr.flush();// BufferedReader can't read it
2. Server:
openServer();// port 1982
while(true) {
Socket clientSocket = null;
// listen to connection.
clientSocket = echoServer.accept();
DataInputStream inStr = new DataInputStream(
clientSocket.getInputStream());
//System.out.println("M1: Got msg " + inStr.readUTF());// It showed the content
BufferedReader bfReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("got Messages: ");
String strLine = "";
// Don't show anything
while ((strLine = bfReader.readLine()) != null) {
System.out.println(strLine);
}
}
You can't. If you use writeUTF() at one end, you have to use readUTF() at the other end.
You just have to decide which API you're going to use, instead of trying to mix and match them.
You want to read the files as either text e.g. BufferedReader OR binary e.g. DataInputStream. So you can't use both.
Server.java
public class Server
{
public static void main(String[] args)
{
DataInputStream inStr = null;
String str;
openServer();// port 1982
while(true)
{
Socket clientSocket = null;
// listen to connection.
clientSocket = echoServer.accept();
try
{
inStr = new DataInputStream(clientSocket.getInputStream());
str = inStr.readUTF();
System.out.print((String) str);
System.out.flush();
}
catch (IOException io)
{
System.err.println("I/O error occurred: " + io);
}
catch (Throwable anything)
{
System.err.println("Exception caught !: " + anything);
}
finally
{
if (inStr != null)
{
try
{
inStr.close();
}
catch (IOException io)
{
System.err.println("I/O error occurred: " + io);
}
}
}
}
}
}
I have a simple Fileserver and Client (code from the web) that let me send files to my other laptop inside my home LAN. Now, the file sent from the server to the client is hardcoded but i want to prompt user at client-side to input a filename, send it to the server and send back the specified file. My code looks like this:
Server
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args) {
BufferedOutputStream outputStream;
BufferedInputStream inputStream;
FileInputStream fileInput;
String file = "C:/java/file.mp4";
try {
ServerSocket socket = new ServerSocket(12345);
while(true) {
Socket clientSocket = socket.accept();
outputStream = new BufferedOutputStream(clientSocket.getOutputStream());
fileInput = new FileInputStream(file);
inputStream = new BufferedInputStream(fileInput);
int packetToSend = -1;
byte[] buffer = new byte[8192];
while((packetToSend = inputStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, packetToSend);
System.out.println("sending " + packetToSend + " bytes");
outputStream.flush();
}
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
And thats the Client Code (IPAdress of the Server is argument s[0] and the path to save the file is s[1] in main method.
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] s) {
try {
String address = new String(s[0]);
String fileToSave = new String(s[1]);
Socket socket = new Socket(address,12345);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
FileOutputStream fos = new FileOutputStream(fileToSave);
int n;
byte[] buffer = new byte[8192];
System.out.println("Connected");
while ((n = bis.read(buffer)) > 0) {
System.out.println("received "+n+" bytes");
fos.write(buffer, 0, n);
fos.flush();
}
System.out.println("recieved");
}
catch(Exception e) {
e.printStackTrace();
}
}
}
I want to promt the user on client side to input a filename after client is connected to send to the server and the server should send that file.
i tried to put this in client side after System.out.println("connected");
System.out.print("Insert filename to download: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = null;
try {
input = reader.readLine();
} catch (IOException ioe) {
System.out.println("Eingabe konnte nicht verarbeitet werden!");
System.exit(1);
}
System.out.println("Eingabe: " + input);
and on server side i put this after outputStream = new BufferedOutputStream(clientSocket.getOutputStream()); to override the hardcoded filename at the beginning of server class.
inputStream = new BufferedInputStream(clientSocket.getInputStream());
fileInputStream = new FileInputStream(inputStream);
fileInputStream = new BufferedInputStream(fileInput);
Once a connection is established, client side is idle (cant input something) and server side does nothing after writing out to console "new connection".
how can i solve this please?
The client sends to the server the filename. So first you must extract the filename from the socket's input stream. To do that you need to establish a protocol for how information will be sent. This is critical when dealing with TCP streams, which is different from UDP datagrams. Typically two newlines is used to convey the end of a message. But because it is not normal for a filename to have a newline in it, we will use one newline to convey end of message.
We can then use Scanner to extract the filename from the client's socket.
String fileName;
Scanner scanner = new Scanner (clientSocket.getInputStream());
while(scanner.hasNextLine())
{
fileName = scanner.nextLine();
break;
}
fileInputStream = new FileInputStream(fileName);
fileInputStream = new BufferedInputStream(fileInput);
In this example the fileName must be the absolute path to that file as its sits in the server's file system. In future versions you might want to use a directory on the server where files are stored and the client can give you the relative path to file from that directory. Here is how that would look like.
String fileName;
Scanner scanner = new Scanner (clientSocket.getInputStream());
while(scanner.hasNextLine())
{
fileName = scanner.nextLine();
break;
}
fileInputStream = new FileInputStream(FILE_DIR + fileName);
fileInputStream = new BufferedInputStream(fileInput);
The variable FILE_DIR would look something like:
static String FILE_DIR = "C:/java/";
And the file that the client would send over would just be file.mp4
EDIT 1:
Here is the Client code with the recommendations. Please note that this test quality code, not production code.
import java.net.*;
import java.io.*;
public class Client {
static String FILE_DIR = "./";
public static void main(String[] s) throws IOException {
/**
* Establish socket using main args.
*/
String address = s[0];
while (true) {
/**
* Get the file name from the user.
*/
System.out.print("Insert filename to download: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String fileName = null;
try {
fileName = reader.readLine();
} catch (IOException ioe) {
System.out.println("Eingabe konnte nicht verarbeitet werden!");
System.exit(1);
}
System.out.println("Eingabe: " + fileName);
/**
* Create the socket.
*/
Socket socket = new Socket(address, 12345);
/**
* With file name in hand, proceed to send the filename to the
* server.
*/
//...put in try-with-resources to close the outputstream.
try (BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream())) {
System.out.println("Connected: Sending file name to server.");
//...send file name plus a newline.
bos.write((fileName + '\n').getBytes());
bos.flush();
/**
* Get the file contents and save to disk.
*/
//...wrap input stream in DataInpuStream for portability.
//...put in try-with-resource to close the input stream.
try (BufferedInputStream bis = new BufferedInputStream(new DataInputStream(socket.getInputStream()))) {
DataOutputStream fos = new DataOutputStream(new FileOutputStream(fileName));
int n;
byte[] buffer = new byte[8192];
System.out.println("Connected: Recieving file contents from server.");
while ((n = bis.read(buffer)) > 0) {
System.out.println("received " + n + " bytes");
fos.write(buffer, 0, n);
fos.flush();
}
System.out.println("recieved");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
and here's the server code. Please note the server is retrieving the file from local directory called ./files/, please change that to whatever directory you want.
import java.net.;
import java.io.;
import java.util.Scanner;
public class Server {
static String FILE_DIR = "./files/";
public static void main(String[] args) {
BufferedInputStream inputStream;
FileInputStream fileInput;
try {
ServerSocket socket = new ServerSocket(12345);
while (true) {
Socket clientSocket = socket.accept();
/**
* Get the file name from the client. File name is one per line.
*/
//...put in trye-with-resources to close InputStream for us.
try (InputStream inputFromClient = clientSocket.getInputStream()) {
System.out.println("Connected: Getting file name from client.");
Scanner scanner = new Scanner(inputFromClient);
String fileName;
if (scanner.hasNextLine()) {
fileName = scanner.nextLine();
System.out.println("File name = " + fileName);
} else {
//...no line found, continue. consider logging an error or warning.
continue;
}
/**
* With fileName in hand, we can proceed to send the
* contents of the file to the client.
*/
fileInput = new FileInputStream(fileName);
//...use DataInputStream for more portable code
DataInputStream dataInput = new DataInputStream(fileInput);
inputStream = new BufferedInputStream(dataInput);
int packetToSend = -1;
byte[] buffer = new byte[8192];
//...consider closing the OutputStream to let the client know.
//...use try-with-resource to close the outputStream for us.
//...wrap your outputStream in DataOutputStream
try (BufferedOutputStream outputStream = new BufferedOutputStream(new DataOutputStream(clientSocket.getOutputStream()))) {
while ((packetToSend = inputStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, packetToSend);
System.out.println("sending " + packetToSend + " bytes");
outputStream.flush();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
What I am trying to do is to read in data from a socket connection then write all of that to a file. My reader and all the related statements are below. Any ideas why it is not working? If you can see a more efficient way to do this that would also be useful.
(My full code does successfully connect to the socket)
EDIT: Added more of my code.
public static void main(String args[]) throws IOException
{
Date d = new Date();
int port = 5195;
String filename = "";
//set up the port the server will listen on
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(port));
while(true)
{
System.out.println("Waiting for connection");
SocketChannel sc = ssc.accept();
try
{
Socket skt = new Socket("localhost", port);
BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
FileWriter logfile = new FileWriter(filename);
BufferedWriter out = new BufferedWriter(logfile);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while ((inputLine = stdIn.readLine()) != null)
{
System.out.println("reading in data");
System.out.println(inputLine);
out.write(inputLine);
System.out.println("echo: " + in.readLine());
}
sc.close();
System.out.println("Connection closed");
}
You program requires you to type in a line for every line you read from the socket. Are you typing enough lines?
The lines you read from the console are written to the file, did you expect the lines from the socket to be written to the file?
Where are you closing the file (and the socket)
Another approach is to use a utility like Apache IOUtils
Socket skt = new Socket("localhost", port);
IOUtils.copy(skt.getInputStream(), new FileOutputStream(filename));
skt.close();
I think there's a typo in this line:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
Change "System.in" to just "in":
BufferedReader stdIn = new BufferedReader(new InputStreamReader(in));
FYI, here is how I like to read sockets. I prefer to avoid the string encoding offered by the readers, and just go straight for raw bytes:
byte[] buf = new byte[4096];
InputStream in = skt.getInputStream()
FileOutputStream out = new FileOutputStream(filename);
int c;
while ((c = in.read(buf)) >= 0) {
if (c > 0) { out.write(buf, 0, c); }
}
out.flush();
out.close();
in.close();
Oh, cute, turns out that code is essentially what IOUtils.copy() does (+1 to Peter Lawrey!):
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/CopyUtils.java?view=markup#l193