client/server to send a file get stuck somewhere - java

I have implemented a client/server to send files . When there is no more messages exchanged after sending the file , the code works perfectly , but if the client sends some string to the server directly after the code of receiving the file both client and server stop doing anything and the file is not sent it's something like if they both get stuck in deadlock but I'm not really sure :
Here is the code to send the file without sending anything after it , which works:
Client
String filename;
BufferedReader UIn = new BufferedReader(new InputStreamReader(System.in));
Socket peer = new Socket("localhost",9999);
System.out.print("Enter the file name to download :");
filename= UIn.readLine();
///////////////////////////////
DataOutputStream OutToServer;
OutToServer = new DataOutputStream(peer.getOutputStream());
OutToServer.writeBytes(filename+"\n");
FileOutputStream fos = new FileOutputStream(new File("D:/new.txt"));
BufferedOutputStream out = new BufferedOutputStream(fos);
InputStream in = peer.getInputStream();
buffer = new byte[1024];
while((count=in.read(buffer))>0)
{
fos.write(buffer, 0, count);
System.out.println(buffer);
}
fos.close();
System.out.println("done");
Server:
ServerSocket server =null;
try {
server = new ServerSocket(9999);
while(true)
{
client= server.accept();
//System.out.println("Connection accepted");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
DataOutputStream outToclient =new DataOutputStream(client.getOutputStream());
String request=inFromClient.readLine();
file = new File(request);
if (file.exists())
{
OutputStream out = client.getOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
while((count =in.read(buffer)) >0)
{
out.write(buffer,0,count);
out.flush();
}
}
// System.out.println(request);
// outToclient.writeBytes("alaa\n");
}
} catch (IOException ex) {
Logger.getLogger(ServerWork.class.getName()).log(Level.SEVERE, null, ex);
}
But if I try to send anything after the loop between client and server it stops working . Is it because I'm using readLine() and writeBytes()?

You are using both DataOutputStream and OutputStream. I think that they
should work together but what I guess you should do is to flush the buffer (or close it).
After you're done writing everything you want to send, some data may still be in the buffer. Now you will have to flush the buffer, to force it to send all the data.(as it is said here).
outToclient.writeBytes("alaa\n");
outToclient.flush();

Related

JAVA socket closed down before it Accepts data

I am unable to send data from the server(python) to the client (android java). Java client socket gets shutdown before it accepts data from the server.
no Error on the Python side it sends data as well but the java client socket is closed and doesn't accept data
Error W/System.err: java.net.SocketException: Socket is closed
at java.net.Socket.getInputStream(Socket.java:923) W/System.err: at
com.example.smd.TcpDataHandler.doInBackground(TcpDataHandler.java:66)
at com.example.smd.TcpDataHandler.doInBackground(TcpDataHandler.java:20)
python code
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('ip' , port))
server_socket.listen(10)
print("server is listening")
(client_socket,client_adress) = server_socket.accept()
print("Socket completed")
#client_socket.shutdown(socket.SHUT_WR)
#while True:
print('waitingg.....................')
try:
data2=b''
while True:
buf = client_socket.recv(65535)
data2 += buf
if not buf:
break
client_input = data2
print("data recieve ")
b=base64.b64decode(client_input)
#print(b)
imageStream = io.BytesIO(client_input)
imageFile = Image.open(imageStream)
# i = Image.fromarray(imageFile, mode='L').convert('1')
imageFile.LOAD_TUNCATED_IMAGES=True
print(imageFile.size)
#this is the image ,here you cna verify via image size
modelRes=test(imageFile)
modelRes=modelRes[0]
modelRes= int(modelRes[0])
data = database(decode(imageFile))
print(data)
#json_obj = [{ "model_res": modelRes , "decode_data": data}]
x = { "model_res": modelRes, "decode_res": data}
# convert into JSON:
data = json.dumps(x)
print('data is : '+data)
client_socket.send(data.encode())
print('data sended')
client_socket.shutdown(socket.SHUT_WR)
print('Reciving BYE message')
data3 = client_socket.recv(1024).decode()
print('Program ended : '+data3)
client_socket.close()
server_socket.close()
except Exception as e:
print(e)
JAVA codee
socket=new Socket("ip", port);
System.out.println("Socket donee : ");
byte[] bArray = new byte[(int) file.length()];
try{
fis = new FileInputStream(file);
fis.read(bArray);
fis.close();
}catch(IOException ioExp){
ioExp.printStackTrace();
}
Log.d("Data to bytes"," images has been converted to byte");
out = new DataOutputStream(socket.getOutputStream());
out.write(bArray);
out.flush();
out.close();
Log.d("Data send"," Data has been send Successfully");
Log.d("waiting responce"," Waiting ford data from Python");
InputStreamReader streamReader= new
InputStreamReader(socket.getInputStream());
BufferedReader reader= new BufferedReader(streamReader);
String value= reader.readLine();
System.out.println(value);
Log.d("Data Revieve"," Recieve data Successfully");
reader.close();
dataRec="";
dataRec=value;
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
System.out.println("Sending BYE MSG");
// write the message we want to send
dataOutputStream.writeUTF("Byeee serverrrrrr");
dataOutputStream.flush(); // send the message
dataOutputStream.close(); // close the output stream when we're done.
socket.close();
Log.d("Socket closed "," Socket has been Successfully");
In your java code you have the lines
out = new DataOutputStream(socket.getOutputStream());
out.write(bArray);
out.flush();
out.close();
That last line out.close(); also closes the socket. This may not be obvious. DataOutputStream extends FilterOutputStream and inherits its close method. FilterOutputStream.close() also closes the wrapped OutputStream which in this case is socket.getOutputStream(). The Javadocs for socket.getOutputStream() state
Closing the returned OutputStream will close the associated socket.
Since your python code reads until end-of-stream/end-of-file, you need some way for Java signal to signal to its python peer that it is finished writing data. Java provides this through the socket.shutdownOutput() method. Thus, if you replace out.close(); with socket.shutdownOutput() you should get the effect you need:
out = new DataOutputStream(socket.getOutputStream());
out.write(bArray);
out.flush();
socket.shutdownOutput();

TCP Video file transfer

I'm trying to make a video file transfer but am having problems getting the server to start sending bytes.
The first step is for the client to connect, the socket gets accepted. Then the client sends the video file name but the server never reads this.
This is the code for the server up until it blocks:
try(ServerSocket serverSocket = new ServerSocket(4005))
{
Socket socket = serverSocket.accept();
System.out.println("accepted");
OutputStream os = socket.getOutputStream();
BufferedReader receiveReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("This gets printed");
String request = receiveReader.readLine();//never passes this line
System.out.println("This doesn't get printed");
and this is the client up until it blocks waiting for the server to send the video bytes:
try(Socket socket = new Socket(IPAddress, 4005))
{
byte[] messageBytes = new byte[10000];
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeBytes("REQUEST;"+videoPath);//This is the line that should send the bytes for the server to read, so it won't block.
String home = System.getProperty("user.home");
String path = home+"\\Downloads" + videoName;
path = path.trim();
FileOutputStream fos = new FileOutputStream(path);
BufferedOutputStream bos = new BufferedOutputStream(fos);
InputStream is = socket.getInputStream();
int bytesRead = 0;
System.out.println("Downloading file...");
while((bytesRead = is.read(messageBytes))!=-1)//This blocks here
Why on earth isn't the server reading the "Request" + videoPath bytes that the server is sending? I tried outputStream.flush() as well, no luck.
Usual problem. You're reading a line but you aren't writing a line. Add a line terminator to the sent message.
When you fix this you will then discover that you can't mix buffered streams and readers on the same socket. I suggest you do all the I/O via the DataInput/OutputStream classes, using read/writeUTF() for the name.
If you're sending multiple files see my answer there.

Send request line + File using Sockets - java

I am trying to send a "request line" and a file through a socket.
Client (sender)
Socket socket = new Socket(hostName, SOCKET_PORT);
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
FileInputStream fis = new FileInputStream(fileName);
os.writeBytes("PUT c:\dev\foo\helloworld.txt" + "\r\n")
byte[] buffer = new byte[1024];
int bytes;
while((bytes = fis.read(buffer)) != -1 ) {
try {
os.write(buffer, 0, bytes);
} catch (IOException e) {e.printStackTrace();}
}
Sever (receiver)
ServerSocket serverSocket = new ServerSocket(SOCKET_PORT);
Socket clientSoc = serverSocket.accept();
InputStream inputStream = clientSoc.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String requestLine = bufferedReader.readLine();
File currentFile = (File)new ObjectInputStream(inputStream).readObject(); //This doesn't work
byteSequence = new byte[new Long(currentFile.length()).intValue()];
for(int i =0; i<currentFile.length();i++){
byteSequence[i] = (byte)clientSoc.getInputStream().read();
}
try {
FileOutputStream newFile = new FileOutputStream(currentFile.getName());
newFile.write(byteSequence,0, byteSequence.length);
} catch (IOException e) {e.printStackTrace();}
I am able to read the request line on the server but when I attempt to read the file it throws an exception (line below).
File currentFile = (File)new ObjectInputStream(inputStream).readObject();
java.io.Stream.CorruptedException:
java.io.StreamCorruptedException: invalid stream header: 0A48656C
What exactly am I doing wrong?
You are trying to access an object that was not even passed to the socket.. you only passed a byte of string to the server but you never pass an Object to the server using the ObjectOutputStream..

Resume file upload/download after lost connection (Socket programming)

I'm writing a program to download/upload a file between a client and server using socket programming. The code i've written till now works in the sense that i can sucesfully transfer files. However , if a connection fails due to problem in the network/client/server while a download / upload is occuring.. i need to RESUME the download/upload from the original point(Do not want the originally sent data to be resent). I'm not sure how to go about this. I'm reading the file into a byte array and sending it across the network. My initial idea is that everytime i'm downloading.. i should check if the file already exists and read the data into a byte array --> send the data to the server for comparison and then return the remaining data from the server file by comparing the two byte arrays. But this seems inefficient and takes away the point of resuming a download(since i'm sending the data again).
Note: The file name is an unique identifier.
I would really appreciate it if anybody could give me suggestions as to how i should implement the file resume functionality?
Server side code:
package servers;
import java.io.*;
import java.net.*;
import java.util.Arrays;
public class tcpserver1 extends Thread
{
public static void main(String args[]) throws Exception
{
ServerSocket welcomeSocket = null;
try
{
welcomeSocket = new ServerSocket(5555);
while(true)
{
Socket socketConnection = welcomeSocket.accept();
System.out.println("Server passing off to thread");
tcprunnable tcprunthread = new tcprunnable(socketConnection);
Thread thrd = new Thread(tcprunthread);
thrd.start();
System.out.println(thrd.getName());
}
}
catch(IOException e){
welcomeSocket.close();
System.out.println("Could not connect...");
}
}
}
class tcprunnable implements Runnable
{
Socket socke;
public tcprunnable(Socket sc){
socke = sc;
}
public void download_server(String file_name)
{
System.out.println("Inside server download method");
try
{
System.out.println("Socket port:" + socke.getPort());
//System.out.println("Inside download method of thread:clientsentence is:"+clientSentence);
// Create & attach output stream to new socket
OutputStream outToClient = socke.getOutputStream();
// The file name needs to come from the client which will be put in here below
File myfile = new File("D:\\ "+file_name);
byte[] mybytearray = new byte[(int) myfile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myfile));
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
System.out.println("Arrays on server:"+Arrays.toString(mybytearray));
outToClient.flush();
bis.close();
}
catch(FileNotFoundException f){f.printStackTrace();}
catch(IOException ie){
ie.printStackTrace();
}
}
public void upload_server(String file_name){
try{
byte[] mybytearray = new byte[1024];
InputStream is = socke.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("D:\\ "+file_name);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
bos.write(mybytearray, 0, bytesRead);
do {
baos.write(mybytearray);
bytesRead = is.read(mybytearray);
}
while (bytesRead != -1);
bos.write(baos.toByteArray());
System.out.println("Array on server while downloading:"+Arrays.toString(baos.toByteArray()));
bos.close();
}
catch(FileNotFoundException fe){fe.printStackTrace();}
catch(IOException ie){ie.printStackTrace();}
}
#Override
public void run()
{
try
{
System.out.println("Server1 up and running" + socke.getPort());
// Create & attach input stream to new socket
BufferedReader inFromClient = new BufferedReader
(new InputStreamReader(socke.getInputStream()));
// Read from socket
String clientSentence = inFromClient.readLine();
String file_name = inFromClient.readLine();
System.out.println("Sever side filename:" + file_name);
try{
if(clientSentence.equals("download"))
{
download_server(file_name);
}
else if(clientSentence.equals("upload"))
{
upload_server(file_name);
System.out.println("Sever side filename:" + file_name);
}
else
{
System.out.println("Invalid input");
}
}
catch(NullPointerException npe){
System.out.println("Invalid input!");
}
socke.close();
}
catch(IOException e)
{
e.printStackTrace();
System.out.println("Exception caught");
}
}
}
Client side code:
package clients;
import java.io.*;
import java.net.*;
import java.util.Arrays;
public class tcpclient1
{
public static void main (String args[]) throws Exception
{
// Create input stream to send sentence to server
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = null;
while(true){
System.out.println("Please enter the server you want to use");
System.out.println("Enter 1 for Server 1 and 2 for Server2");
String server_choice = inFromUser.readLine();
if(server_choice.equals("1")){
// Create client socket to connect to server
// The server to use will be specified by the user
clientSocket = new Socket("localhost",5555);
break;
}
else if(server_choice.equals("2"))
{
clientSocket = new Socket("localhost",5556);
break;
}
else
{
System.out.println("Invalid entry");
}
}
System.out.println("Please enter download for dowloading");
System.out.println("Please enter upload for uploading");
// sentence is what'll be received from input jsp
String sentence = inFromUser.readLine();
if(sentence.equals("download"))
{
download_client(clientSocket,sentence);
}
else if(sentence.equals("upload"))
{
upload_client(clientSocket,sentence);
}
else
{
System.out.println("Invalid input");
}
clientSocket.close();
}
public static void download_client(Socket clientSocket , String sentence)
{
try{
// Create output stream attached to socket
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
// Send line to server
outToServer.writeBytes(sentence+'\n');
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the name of file to download:");
String file_to_download = inFromUser.readLine();
if(searching(file_to_download))
{
// Read local file and send that to the server for comparison
// DONT THINK THIS IS THE RIGHT WAY TO GO ABOUT THINGS SINCE IT BEATS THE PURPOSE OF RESUMING A DOWNLOAD/UPLOAD
}
// Send filetodownload to server
outToServer.writeBytes(file_to_download+'\n');
byte[] mybytearray = new byte[1024];
InputStream is = clientSocket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("E:\\ "+file_to_download);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
bos.write(mybytearray, 0, bytesRead);
do {
baos.write(mybytearray);
bytesRead = is.read(mybytearray);
}
while (bytesRead != -1);
bos.write(baos.toByteArray());
System.out.println("Array on client while downloading:"+Arrays.toString(baos.toByteArray()));
bos.close();
}
catch(FileNotFoundException fe){fe.printStackTrace();}
catch(IOException ie){ie.printStackTrace();}
}
public static void upload_client(Socket clientSocket, String sentence)
{
try{
// Create output stream attached to socket
DataOutputStream outToServer1 = new DataOutputStream(clientSocket.getOutputStream());
// Send line to server
outToServer1.writeBytes(sentence+'\n');
System.out.println("In the client upload method");
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the name of file to upload:");
String file_to_upload = inFromUser.readLine();
//System.out.println("Cline side file name:"+file_to_upload);
outToServer1.writeBytes(file_to_upload+'\n');
System.out.println(file_to_upload);
OutputStream outtoserver = clientSocket.getOutputStream();
File myfile = new File("E:\\ "+file_to_upload);
byte[] mybytearray = new byte[(int) myfile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myfile));
bis.read(mybytearray, 0, mybytearray.length);
outtoserver.write(mybytearray, 0, mybytearray.length);
System.out.println("filename:"+file_to_upload+"Arrays on client while uploading:"+Arrays.toString(mybytearray));
outtoserver.flush();
bis.close();
}
catch(FileNotFoundException fe){fe.printStackTrace();}
catch(IOException ie){ie.printStackTrace();}
}
public static boolean searching(String file_name)
{
String file_path = "E:\\ "+file_name;
File f = new File(file_path);
if(f.exists() && !f.isDirectory()) { return true; }
else
return false;
}
}
The above code runs fine for transferring files between the client and server.
Again , would really appreciate any help!
There are many ways which you can do this, I suggest you to create a separate type of request to the server that accepts the file's name and file position which is the position where in the file where the connection failed.
That's how you will get the file from the server in the client's side:
int filePosition = 0;
InputStream is = clientSocket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
do {
baos.write(mybytearray);
bytesRead = is.read(mybytearray);
if(bytesRead != -1)
filePosition += bytesRead;
}
while (bytesRead != -1);
Now if the connection got interrupted for some reason you can send a request again to the server with the same file name and the filePosition, and the server will send the file back like this:
OutputStream outToClient = socke.getOutputStream();
// The file name needs to come from the client which will be put in here below
File myfile = new File("D:\\ "+file_name);
byte[] mybytearray = new byte[(int) myfile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myfile));
bis.skip(filePosition) //Advance the stream to the desired location in the file
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
System.out.println("Arrays on server:"+Arrays.toString(mybytearray));
outToClient.flush();
bis.close();
And in the client you can open the file stream and specify append = true in the constructor like this:
FileOutputStream fos = new FileOutputStream("D:\\ "+file_name, true);
This could be one way to do this, there are a lot more options. And I also suggest verify the files after the transfer using some hash function like MD5 for example, it creates unique stamp for a given input and it always outputs same result for the same input, which means, you can create the stamp from the same file both in the server and in the client and if the file is truly the same, it will generate the same stamp. Since the stamp's size is very small relative to the file it self and it is also fixed, it can be send between the client/server without much overhead.
You can generate an MD5 hash with this code:
MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = Files.newInputStream(Paths.get("file.txt"))) {
DigestInputStream dis = new DigestInputStream(is, md);
/* Read stream to EOF as normal... */
}
byte[] digest = md.digest();
(taken from: Getting a File's MD5 Checksum in Java)
Basically, when requesting a download You should attach information about how many bytes need to be skipped (0 on new download). You should get this information from part of the file that you have downloaded (read it's size). Server should skip given count of bytes and send back the remainder of file. Client should append this to the existing file. For sanity check, You could add some file hash checking in the end, to ensure You got the file correctly.

Send string to client upon command JAVA

So I am trying to have a sever sit and listen waiting for a connection from a client. The client sends over some string and the sever does some action based on whats received. Now what I would like to happen is the client sends over some command asking for data back and have the server get what it needs to and send the string back.
Not a big deal right? Well for some reason I can't get it working, my best guess is that its not closing the socket properly. I can't figure out why it wouldn't or what I am doing wrong.
Client
String data = "";
DataOutputStream outToServer = null;
BufferedReader input;
try {
outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes("GETDATA");
outToServer.flush();
input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
data = input.readLine();
Log.d("ANSWER: ", data);
input.close();
} catch (IOException e) {
Log.d("Error: ", e.toString());
}
Server
ServerSocket listeningSocket = new ServerSocket(9008);
BufferedReader fromClient ;
PrintStream os;
while(true) {
Socket clientSocket = listeningSocket.accept();
ServerConnection clientConnection = new ServerConnection(clientSocket);
os = new PrintStream(clientSocket.getOutputStream());
fromClient= new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
if(fromClient.readLine().equals("GETDATA")){
os.println("DATA");
os.flush();
clientSocket.wait();
clientSocket.close();
}
else{
clientConnection.run();
}
}
Any ideas?
here is your error
outToServer.writeBytes("GETDATA");
the right code is
outToServer.writeBytes("GETDATA\n");
as your using readline you should send a full line with line break

Categories