Sends files from client to server - java

In the below codes,I am trying to let the server-side to select the file from the client and sends it, so basically all the work is done on the server side. the program works by running the server first wait for client to run, make a connection, then the server sends the place of the file to the client-side outReader.write("B://ghassar/ghassar.txt"); the client reads the location and sends the file. I have run the debug and once the server reads this code String filename = inReader.readLine(); it stops and it gets in like a loop, can anyone help me to solve the problem
/ Server.java
/*
* Server waits for a connection to be established by client
*
*/
import java.io.*;
import java.net.*;
class Server
{
public static void main(String args[])throws Exception
{
System.out.println("Server running...");
/* Listen on port 5555 */
ServerSocket server = new ServerSocket(222);
/* Accept the sk */
Socket sk = server.accept();
System.out.println("Server accepted client");
// to recive from client
InputStream input = sk.getInputStream();
//read what is coming
BufferedReader inReader = new BufferedReader(new InputStreamReader(sk.getInputStream()));
//write to client
BufferedWriter outReader = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
outReader.write("B://ghassar/ghassar.txt");
outReader.flush();
/* Read the filename */
String filename = inReader.readLine();
if (filename.equals("ghassar.txt") ){
/* Reply back to client with READY status */
outReader.write("READY\n");
outReader.flush();
}
/* Create a new file in the libya directory using the filename */
FileOutputStream wr = new FileOutputStream(new File("B://libya/ "+ filename));
byte[] buffer = new byte[sk.getReceiveBufferSize()];
int bytesReceived = 0;
while((bytesReceived = input.read(buffer))>0)
{
/* Write to the file */
wr.write(buffer,0,bytesReceived);
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
public class Client {
public static void main(String args[]){
Client clientForm = new Client();
clientForm.action();
}
public void action() {
try{
/* Try to connect to the server on localhost, port 5555 */
Socket sk = new Socket("localhost", 222);
OutputStream output = sk.getOutputStream();
/* the steam to send the staff*/
OutputStreamWriter outputStream = new OutputStreamWriter(sk.getOutputStream());
/* steam to recive staff */
BufferedReader inReader = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String serverStatus = inReader.readLine(); // Read the first line
String filename = serverStatus;//fileDlg.getSelectedFile().getAbsolutePath();
outputStream.write("ghassar.txt");
outputStream.flush();
/* If server is ready, send the file */
if ( serverStatus.equals("READY") ){
FileInputStream file = new FileInputStream(filename);
byte[] buffer = new byte[sk.getSendBufferSize()];
int bytesRead = 0;
while((bytesRead = file.read(buffer))>0)
{
output.write(buffer,0,bytesRead);
}
output.close();
file.close();
sk.close();
System.out.println("File sent");
}
}
catch (Exception ex){
/* Catch any errors */
System.out.println("not File sent");
}
}
}

I suggest you to use PrintWriter instead of BufferedWriter. There is no need to call flush after each line and simply use println() method along with auto-flush feature to add a new line as well.
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output.
These methods use the platform's own notion of line separator rather than the newline character.
There is no need to append \n in the message itself.
Sample code:
// here true means auto flush when `println()` method is called
PrintWriter w=new PrintWriter(new OutputStreamWriter(sk.getOutputStream()),true);
w.println(message);
Possible cause in the code:
The problem may be at below lines where \n is not added in the end of the string in write() method before flushing and at client side the method readLine() is used to read it.
BufferedWriter outReader = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
outReader.write("B://ghassar/ghassar.txt");
outReader.flush();
Note: you can use BufferedWriter#newLine() instead of \n that writes a line separator. The line separator string is defined by the system property line.separator, and is not necessarily a single newline ('\n') character.

Related

Transferring binary data using sockets in Java

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.

BufferReader stuck in readline()

I am making an HTTP server and HTTP web client for simple Http request and response.
This is the code for Server
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer{
public static void main(String[] args) throws Exception{
//storing port number
int port = 2048;
//open socket and wait for TCP connection
ServerSocket serverConnect = new ServerSocket(port);
System.out.println("Server started.\nListening for connections on port : " + port + " ...\n");
// we listen until user halts server execution
while (true) {
//Construct an object to process the HTTP request message.
//This will call another class where we do everything else
HttpRequest request = new HttpRequest(serverConnect.accept());
//create a new thread to process the request
Thread thread = new Thread(request);
thread.start();
} //end of while
}//end of main
}//end of the class webServer
The code for HttpRequest class is as follow:
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable{
final static String CRLF = "\r\n";
Socket socket;
//start of constructor
public HttpRequest(Socket socket) throws Exception{
this.socket=socket;
}//end of constructor
//Implement the run() method of the Runnable interface.
public void run(){
try{
processRequest();
}
catch(Exception e){
System.out.println(e);
}
}//end of run
private void processRequest() throws Exception{
//Get a reference to the scoket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
//set up the stream filters
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//Get the request line of the HTTP request message.
String requestLine = br.readLine();
//Display the request line
System.out.println();
System.out.println(requestLine);
//Get and display the header lines.
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println(headerLine);
}
//System.out.println(requestLine);
//Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); //skip over the method, which should be. "GET"
String fileName = tokens.nextToken();
//Prepend a "." so that file request is within the current directory
fileName = "." + fileName;
//printing for test
//System.out.println(fileName);
//Open the requested file
FileInputStream fis = null;
boolean fileExists = true;
try{
fis = new FileInputStream(fileName);
}
catch(FileNotFoundException e){
fileExists = false;
}
//Construct the response message
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if(fileExists){
statusLine = tokens.nextToken();
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
}
else{
statusLine = "HTTP/1.1 404 File Not Found";
contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<html><head><title>Not Found </title></head>" +
"<BODY>Not Found</body></html>";
}
//send the status line
os.writeBytes(statusLine);
//send the content Type
os.writeBytes(contentTypeLine);
//send a blank line to indicate the end of the header lines
os.writeBytes(CRLF);
//send the entity Body
if(fileExists){
sendBytes(fis, os);
fis.close();
}
else{
os.writeBytes(entityBody);
os.writeBytes(CRLF);
}
//Close scokets and streams.
fis.close();
os.close();
br.close();
socket.close();
}//end of processRequest
private static String contentType(String fileName){
if(fileName.endsWith(".htm") || fileName.endsWith(".html")){
return "text/html";
}
if(fileName.endsWith(".gif")){
return "image/gif";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")){
return "image/jpeg";
}
return "application/octet-stream";
}// end of contentType
private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception{
//Construct a 1k buffer to hold bytes on their way to the Socket
byte[] buffer = new byte[1024];
int bytes = 0;
//Copy requested file into the scoket's output stream.
while((bytes = fis.read(buffer)) != -1){
os.write(buffer, 0, bytes);
}//end of while
}//end of sendBytes
} // end of the class
The Code works fine when I make a request from Chrome webbrowser. However, I made WebClient as well. When I make request from WebClient, I am stuck as the program runs forever.
As far I have tracked, the pointer does not move from the br.readline on the while loops on the Server Side.
The code for my client is as follow.
import java.io.*;
import java.net.*;
import java.util.*;
public class WebClient{
final static String CRLF = "\r\n";
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
// System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("GET /" +args[2] +" HTTP/1.1");
out.writeUTF(CRLF);
out.writeUTF("Host: "+client.getLocalSocketAddress());
out.writeUTF(CRLF);
out.writeUTF("Connection: close" + CRLF);
out.writeUTF("User-agent: close" + CRLF);
out.writeUTF(CRLF);
//Cache-Control: max-age=0
System.out.println("Just connected to 1 ");
InputStream inFromServer = client.getInputStream();
System.out.println("Just connected to 2 ");
BufferedReader br = new BufferedReader(new InputStreamReader(inFromServer));
System.out.println("Just connected to 3 ");
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
System.out.println("Just connected to 4 ");
client.close();
System.out.println("Just connected to 5 ");
} catch (IOException e) {
e.printStackTrace();
}
}
}//end of the class WebClient
Can anyone help me figure out the problem.
Thanks.
First of all, you have to remove line fis.close(); (right before os.close();) in your HttpRequest class: if no file exists, this line raises NullPointerException because fis is null, so after sending Not Found response to the browser, your server does not close the socket accepted from that browser, that's why even though you see Not Found in your browser, your request never ends.
Secondly, the reason of why your client gets stuck is writeUTF() method that you used for sending request header. Seems that this line out.writeUTF(CRLF); does not really send an empty string but adds some other UTF-related character(s) (you may notice that in your server's console output), so your server gets stuck at while((headerLine = br.readLine()).length()!=0) waiting for the client to send an empty string, but never receives it. You need to replace out.writeUTF(CRLF); with out.writeBytes(CRLF);.
Also, it makes little sense to use BufferedReader for receiving binary files from socket. Reader in general is used with character-input stream, so it is not applicable for your case. You may use InputStream instead, by replacing this fragment:
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
with this (I chose buffer size of 4096, you may replace it with your preferred value):
int readBytes;
byte[] cbuf = new byte[4096];
while((readBytes=inFromServer.read(cbuf, 0, 4096))>-1){
System.out.println("read: " + readBytes);
}
Note: You may easily notice here that InputStream.read() will fetch not only the file itself but also statusLine, contentTypeLine and two CRLFs, so in case if you would like to separate them from the file, you may read them first, by issuing two "readLines" and then fetch the file only by read()
In your server, you use writeBytes()
Writes out the string to the underlying output stream as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits. If no exception is thrown, the counter written is incremented by the length of s.
While you may worry about non-ASCII text, generally this is what you need.
In your client you attempt to use writeUTF()
First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.
While that 2-byte length in the beginning can be useful in other cases, it is not what web servers expect, including yours (and that is correct). So use writeBytes() everywhere in your client, and it will suddenly work:
out.writeBytes("GET /" +args[2] +" HTTP/1.1");
out.writeBytes(CRLF);
out.writeBytes("Host: "+client.getLocalSocketAddress());
out.writeBytes(CRLF);
out.writeBytes("Connection: close" + CRLF);
out.writeBytes("User-agent: close" + CRLF);
out.writeBytes(CRLF);
In fact those extra bytes may be visible in your server output, at least when I ran it in Eclipse, I saw garbage characters, as a combination of mysterious empty space and a tiny question mark in a rectangle (note how they also appear at the end of the lines when CRLF is sent separately):
(The first request is the one issued with writeUTF, and the second one comes from Chrome)

How to send data in a java socket program without closing socket

i created a sever socket program to send a stream data to Apache spark.But data is received by spark after i close the socket or termination of program.i need to send data without closing socket and terminating program.
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class SocketServer {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept();// establishes connection
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
Scanner scanner = new Scanner(System.in);
String s1 = "";
while (!s1.equals("end")) {
s1 = scanner.next();
dout.writeUTF(s1);
dout.flush();
}
ss.close();
} catch (Exception e) {r
System.out.println(e);
}
}
}
i can send data in stream using nc server nc -lk 9999.
EDIT -1 Tried with println
try {
ServerSocket ss = new ServerSocket(6000);
Socket s = ss.accept();// establishes connection
OutputStream ostream = s.getOutputStream();
PrintWriter pwrite = new PrintWriter(ostream, true);
Scanner scanner = new Scanner(System.in);
String s1 = "";
while (!s1.equals("end")) {
s1 = scanner.next();
pwrite.println(s1);
pwrite.flush();
}
ss.close();
} catch (Exception e) {
System.out.println(e);
}
Still not working.
Please help..
Unless Apache Spark is (a) written in Java and (b) calling readUTF() you're using the wrong method to send. You should probably be using a println() method. You also need to close the accepted socket, as well as the server socket.
First of all you should only be instantiating dout once (before the start of the while loop).
Secondly I believe the way it works is that when reading from a socket stream it reads until the end of the stream is reached (ie socket is closed). To finish reading early you'd need to send an "end of stream" without closing it.

BufferedReader reads line only after closing the connection, not after flush()

I've the following Server.java:
public class Main {
public static void main(String args[]) throws Exception{
ServerSocket server = new ServerSocket(12345);
Socket client = server.accept();
OutputStream out = client.getOutputStream();
BufferedWriter writer = new BufferedWriter(new PrintWriter(out));
writer.write("Hello client");
writer.flush(); //After executing of that instruction there is no any output on the client
client.close(); //The client prints "Hello client"
}
}
and the Client.java:
public class Main {
#SuppressWarnings("resource")
public static void main(String args[]) throws Exception{
Socket s = new Socket("localhost", 12345);
BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(r.readLine());
s.close();
}
}
The issue is I can't get the reason why the client prints the string only after the connection was closed, but not after the stream was flushed. I thought flush() send a signal to the client that data-transfering process is over. Since, the client have to read all the data that was being send to it before calling flush(). What's wrong?
readLine() reads a complete line. To know that the line is complete, the reader needs to either find a newline character sequence, or the end of the stream. So it blocks until it sees one of those.
Realize that your client might very well do the following:
out.write("Hello ");
out.flush();
out.write("world!\n");
out.flush();
This sends a single line: "Hello world". And readLine() as its name indicates, is supposed to return that, not 2 lines "Hello " and "World".
So, if you want to send a line, you need to end its line terminator. Otherwise you're not sending a line, but only some characters.
Note that it would be easier if you used a PrintWriter correctly:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));
out.println("Hello client");

Java Socket server side cannot read incoming line of text in play framework application

So I'm having some serious problems with Java's server side socket, which accepts connection, but it can't read anything from BufferedReader, which I have put to read the text stream from socket connection. Code for my threads run(), which I'm creating and running at the first time when any page is loaded.
public void run() {
try{
ServerSocket s = new ServerSocket(4100);
System.out.println("New tcp socket created");
Socket socket = s.accept();
System.out.println("New tcp update connection established.");
InputStream din = socket.getInputStream();
PrintWriter outp = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(din));
System.out.println("Streams created");
String inputline = "nothing yet...";
outp.println("hello from server");
while(true){
System.out.println("Got input from client:" + inputline);
inputline = in.readLine();
if(inputline == null || inputline.equals("exit")){
break;
}
}
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("Updater thread exits.");
}
This prints out everything properly, except for Got input from client: + what ever my client sends with PrintWriter which outputs to a socket.
Client side example:
Socket s = new Socket(serverip, serverDownloadsUpdatePort);
OutputStream dout = s.getOutputStream();
PrintWriter outp = new PrintWriter(dout);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(in.readLine());//This prints out properly, what server sends to client
outp.println("test connection");
outp.println("Can you hear me?");
outp.println("exit");
s.close();
Your client may not be sending end-of-line characters along with its input, causing your server to wait indefinitely at "in.readLine()".
The Javadoc for BufferedReader's readLine method (http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine()) says: "Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed." Make sure that your client is sending input that conforms to this rule.
I was able to see client input using your server with the following client Runnable (but only if I include the "\n"):
public void run() {
try{
Socket writeSocket = new Socket("localhost", 4100);
PrintWriter out =
new PrintWriter(writeSocket.getOutputStream(), true);
out.write("Hello there!\n");
out.flush();
}
catch(Exception e){
e.printStackTrace();
}
}
EDIT: When using println as in the submitter's client example, you don't need to worry about adding "\n", but you do need to flush the socket. One way to make sure this happens is by setting autoFlush=true in the PrintWriter constructor.
I found out that I forgot to set PrintWriter as auto flushable at client side and thats why it didn't work becouse stream didn't got flushed at any time.

Categories