I am developing one program in which a user can download a number of files. Now first I am sending the list of files to the user. So from the list user selects one file at a time and provides path where to store that file. In turn it also gives the server the path of file where does it exist.
I am following this approach because I want to give stream like experience without file size limitation.
Here is my code..
1) This is server which gets started each time I start my application
public class FileServer extends Thread {
private ServerSocket socket = null;
public FileServer() {
try {
socket = new ServerSocket(Utils.tcp_port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
try {
System.out.println("request received");
new FileThread(socket.accept()).start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
2) This thread runs for each client separately and sends the requested file to the user 8kb data at a time.
public class FileThread extends Thread {
private Socket socket;
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public FileThread(Socket socket) {
this.socket = socket;
System.out.println("server thread" + this.socket.isConnected());
//this.filePath = filePath;
}
#Override
public void run() {
// TODO Auto-generated method stub
try
{
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
try {
//************NOTE
filePath=(String) ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File f = new File(this.filePath);
byte[] buf = new byte[8192];
InputStream is = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(is);
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
int c = 0;
while ((c = bis.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
// buf=new byte[8192];
}
oos.close();
//socket.shutdownOutput();
// client.shutdownOutput();
System.out.println("stop");
// client.shutdownOutput();
ois.close();
// Thread.sleep(500);
is.close();
bis.close();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
NOTE: here filePath represents the path of the file where it exists on the server. The client who is connecting to the server provides this path. I am managing this through sockets and I am successfully receiving this path.
3) FileReceiverThread is responsible for receiving the data from the server and constructing file from this buffer data.
public class FileReceiveThread extends Thread {
private String fileStorePath;
private String sourceFile;
private Socket socket = null;
public FileReceiveThread(String ip, int port, String fileStorePath,
String sourceFile) {
this.fileStorePath = fileStorePath;
this.sourceFile = sourceFile;
try {
socket = new Socket(ip, port);
System.out.println("receive file thread " + socket.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
oos.writeObject(sourceFile);
oos.flush();
// oos.close();
File f = new File(fileStorePath);
OutputStream os = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buf = new byte[8192];
int c = 0;
//************ NOTE
ObjectInputStream ois = new ObjectInputStream(
socket.getInputStream());
while ((c = ois.read(buf, 0, buf.length)) > 0) {
// ois.read(buf);
bos.write(buf, 0, c);
bos.flush();
// buf = new byte[8192];
}
ois.close();
oos.close();
//
os.close();
bos.close();
socket.close();
//Thread.sleep(500);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
NOTE : Now the problem that I am facing is at the first time when the file is requested the outcome of the program is same as my expectation. I am able to transmit any size of file at first time. Now when the second file is requested (e.g. I have sent file a,b,c,d to the user and user has received file a successfully and now he is requesting file b) the program faces deadlock at this situation. It is waiting for socket's input stream. I put breakpoint and tried to debug it but it is not going in FileThread's run method second time. I could not find out the mistake here. Basically I am making a LAN Messenger which works on LAN. I am using SWT as UI framework.
A more basic problem.
You are only processing the first socket.
while(true) {
new FileThread(socket.accept()).start();
}
As per the suggestion of Peter Lawrey i removed all the redundant streams code from my source code. Now the changed source code is as follows and the problem remains.
1) No change in FileServer. It is as it is .
2) FileThread
public class FileThread extends Thread {
private Socket socket;
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public FileThread(Socket socket) {
this.socket = socket;
System.out.println("server thread" + this.socket.isConnected());
// this.filePath = filePath;
}
#Override
public void run() {
// TODO Auto-generated method stub
try
{
OutputStream oos = socket.getOutputStream();
oos.flush();
InputStream ois = socket.getInputStream();
byte[] buf = new byte[8192];
ois.read(buf);
filePath = new String(buf);
System.out.println(filePath);
File f = new File(this.filePath);
InputStream is = new FileInputStream(f);
int c = 0;
while ((c = is.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
}
oos.close();
System.out.println("stop");
ois.close();
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
3) FileReceiverThread
public class FileReceiveThread extends Thread {
private String fileStorePath;
private String sourceFile;
private Socket socket = null;
public FileReceiveThread(String ip, int port, String fileStorePath,
String sourceFile) {
this.fileStorePath = fileStorePath;
this.sourceFile = sourceFile;
try {
socket = new Socket(ip, port);
System.out.println("receive file thread " + socket.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
try {
OutputStream oos = socket.getOutputStream();
oos.write(sourceFile.getBytes());
oos.flush();
File f = new File(fileStorePath);
OutputStream os = new FileOutputStream(f);
byte[] buf = new byte[8192];
int c = 0;
// ************ NOTE
InputStream ois = socket.getInputStream();
while ((c = ois.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, c);
os.flush();
}
ois.close();
oos.close();
os.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
is there still something which i am missing ?
Related
This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 5 years ago.
[Editing to explain this posted question is not a duplicate of the quoted question::
The structure, details and routines in the code in the quoted question is very different from mine. In addition, (s)he is sending multiple files and using arraylist in the core. While my code sends one file at a time and I never used arraylist in the core. So what is causing my occasional block may not overlap with the problems with his/her own code
In the first answer, EJP said "You are reading the socket until read() returns -1." I did not do this in my code
In the first answer, EJP said "You need to send the file size ahead of each file. You're already doing a similar thing with the file count. Then make sure you read exactly that many bytes for that file:" I already send exact file size ahead of the file sent in my original posted code so this is not a problem with my code and thus not the solution to the problem i face
The code in the second answer (in the quoted duplicate) serves a different purpose and thus I cannot extrapolate a solution from it to my own code.
The quoted question says "The subsequent files are created in the server folder, but they are 0 bytes" This is not a problem with my own code. When my code runs i receive full file bytes at both client and server ends.
Over all I have read through both the quoted question and the solutions provided and they do not provide any solutions to the problems I faced
thank you]
I am relatively new to client server coding.
I have Android as client and Java server. The system at the moment works like this::
Android client selects/loads a Jpeg image from sdcard, sends int size, string text and image file to server and server sends back integer and a text file with data back to client
My problem at the moment it works perfectly (randomly) only roughly ~60% of the runs. The remainder of the time it blocks permanently and I have to restart server to continue. [Certainly, a little over half of the time, the client-server system sends and receives without a glitch, but ~40% to 45% (permanent block) failure rate is unacceptable]
When it blocks there is no crash dump, stacktrace or error to read.
I have searched previous similar blocking questions and tried to close sockets and inputstream/outputstream and wrappers in different orders varying the permutations, but the success/permanent block rate remained the same
Because there is no stack trace and the randomness, I have no clue what causes the block. Except that using print statements all the server and client code the last prints that hang permanently is in the bytes receiving do-while loop in the server code
I am at a loss on what to do to solve this. I'm hoping experienced minds in this field would help solve this. Full code is below.
Java Server code
public class FileServer {
public static void main(String[] args) throws IOException {
int bytesRead;
int current = 0;
//===============================================
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
//==============================================
InetAddress IP=InetAddress.getLocalHost();
servsock = new ServerSocket(57925);
System.out.println("IP "+IP.getHostAddress()+" ***%% :"+servsock.getLocalPort());
while (true) {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
InputStream is = sock.getInputStream();
//=========================================================
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//=================== read integer from client ============
String number = br.readLine();
System.out.println("integer received from client is "+String.valueOf(number));
byte [] mybytearray = new byte [Integer.valueOf(number)];
//=================== read filename string =====================================
String filename = br.readLine();
System.out.println("integer received from client is "+filename);
//===================== read file data stream bytes ================================
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
System.out.println("1 bytesRead "+bytesRead+" mybytearray.length "+mybytearray.length);
do {
bytesRead = is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
System.out.println("2 current "+current+" bytesRead "+bytesRead);
} while(current < Integer.valueOf(number));
//============================== initialise filename ======================
FileOutputStream fos = new FileOutputStream("C:\\Server root folder\\"+filename+".jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//========================== write bytes to server HDD =======================
bos.write(mybytearray, 0 , current);
System.out.println("4 current "+current);
bos.flush();
long end = System.currentTimeMillis();
// System.out.println("AT SERVER: bytesRead "+bytesRead+" current "+current);
// bos.close();
// ======================== write to-be-rendered data to text file ======================
File pathPlusfile = new File("C:/Server root folder/"+filename+".txt");
appendToFile( pathPlusfile, "file name:: "+filename+"* *", 20999 );
/**/ //================== Send Data in text file to Client ============================================
// send file
mybytearray = new byte [(int)pathPlusfile.length()];
fis = new FileInputStream(pathPlusfile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
//===============================================
os = sock.getOutputStream();
//=========================== send integer to client ===============
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
number = Integer.toString(mybytearray.length);
String sendMessage = number + "\n";
bw.write(sendMessage);
bw.flush();
//========================== send file to client ===================
System.out.println("Sending " + filename + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
//========================= close =================================
System.out.println("number "+number);
System.out.println("Done.");
bos.close();
bw.close();
osw.close();
os.close();
// fos.close();
// bis.close();
// fis.close();
// br.close();
isr.close();
is.close();
closeFile( );
// servsock.close();
// sock.close();
}
}
BufferedReader bufferedReader = null;
String stringObjectData = "";
public int numFromFile = 0;
static BufferedWriter bufferedWriter = null;
public static void appendToFile( File myPathPlusFile, String S, int num ){
try{
bufferedWriter = new BufferedWriter(new FileWriter(myPathPlusFile, true));
bufferedWriter.append( S );
bufferedWriter.append( " " );
bufferedWriter.append( Integer.toString(num) );
bufferedWriter.newLine();
bufferedWriter.flush();
}
catch (IOException e){
e.printStackTrace();
}
}
public static void closeFile( ){
try{
bufferedWriter.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Android Client code
public class FSendfileActivity extends Activity {
private static final int SELECT_PICTURE = 1;
private Socket sock;
private String serverIP = "192.168.1.4";
private String selectedImagePath;
private ImageView img;
final static String qcd = "qcd";
String ImageDir2Client;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Button send;
//====================
public static String FILE_TO_RECEIVED=null;
String cFilename = null;
int bytesRead = -1;
int current = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fsendfile);
ImageDir2Client = Environment.getExternalStorageDirectory().getAbsolutePath();
cFilename = "fromServer000019ggg";
FILE_TO_RECEIVED = ImageDir2Client + "/client root/"+cFilename+".txt";
img = (ImageView) findViewById(R.id.ivPic);
((Button) findViewById(R.id.bBrowse)).setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult( Intent.createChooser( intent, "Select Picture" ), SELECT_PICTURE );
}
});
send = (Button) findViewById(R.id.bSend);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
new Thread(new Runnable() {
#Override
public void run() {
try {
sock = new Socket();
connection(sock, serverIP, 57925);
//=================== prepare buffer to read file ====================
File myFile = new File (selectedImagePath);
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
//=============== read file from sdcard to buffer ==========
bis.read(mybytearray,0,mybytearray.length);
//=================================================================
OutputStream os = sock.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//============================= send size integer ===================
String number = Integer.toString(mybytearray.length);
String sendMessage = number + "\n";
bw.write(sendMessage); // send size integer here
//============================= send file name =====================
String sendMessage2 = cFilename + "\n";
bw.write(sendMessage2); // send size filename here
osw.flush();
bw.flush();
//==================================================================
os.write(mybytearray,0,mybytearray.length); // send file
os.flush();
//================= client receiving data ==============================
InputStream is = sock.getInputStream();
//=================== read integer from client ==========
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
number = br.readLine();
//========================= set incoming file size=============================
mybytearray = new byte [Integer.valueOf(number)];
//========================read file bytes in chunks===============================
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead = is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(current < Integer.valueOf(number));
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bos.write(mybytearray, 0 , current);
bos.flush();
try{
bos.close();
osw.close();
os.close();
// fos.close();
// bw.close();
// br.close();
// isr.close();
bis.close();
sock.close();
// fis.close();
}
catch(Exception e){
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try{
}
catch(Exception e){
e.printStackTrace();
}
}
}
}).start();
}
});
}
public static void connection(Socket s, String serverIP, int port) {
try {
Log.v(qcd, " before connecting ****...");
s.connect(new InetSocketAddress(serverIP, port), 120000);
Log.v(qcd, " socket connection DONE!! ");
} catch (UnknownHostException e) {
e.printStackTrace();
Log.v(qcd, " Unknown host..."+e);
} catch (IOException e) {
e.printStackTrace();
Log.v(qcd, " Failed to connect... "+e);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
img.setImageURI(null);
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
TextView path = (TextView) findViewById(R.id.tvPath);
path.setText("Image Path : " + selectedImagePath);
img.setImageURI(selectedImageUri);
}
}
}
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
}
put the code after the accept into it's own thread and start it each time you get an accept.
edit: added threaded code example:
import java.io.*;
import java.net.*;
import java.util.concurrent.atomic.AtomicInteger;
public class So43462480 {
public interface Consumer<T> { // instead of 1.8 definition
void accept(T t);
}
class Server extends Thread {
Server(ServerSocket serverSocket,Consumer<Socket> consumer) {
super("Server");
this.serverSocket=serverSocket;
this.consumer=consumer;
}
#Override public void run() {
System.out.println("server running on: "+serverSocket);
while(true)
try {
Socket socket=serverSocket.accept();
if(consumer!=null)
consumer.accept(socket);
} catch(IOException e) {
System.out.println(getName()+" caught: "+e);
break;
}
}
final ServerSocket serverSocket;
final Consumer<Socket> consumer;
}
void read(Socket socket) {
InputStream inputStream=null;
try {
inputStream=socket.getInputStream();
BufferedReader in=new BufferedReader(new InputStreamReader(inputStream));
String string=in.readLine();
System.out.println(string+" from: "+socket);
socket.close();
System.out.println(Thread.currentThread().getName()+" succeeded");
} catch(IOException e) {
System.out.println(Thread.currentThread().getName()+" caught: "+e);
}
}
So43462480(String host,Integer service) throws IOException {
ServerSocket serverSocket=new ServerSocket();
SocketAddress socketAddress=new InetSocketAddress(host,service);
serverSocket.bind(socketAddress);
Consumer<Socket> socketConsumer=new Consumer<Socket>() {
#Override public void accept(Socket socket) {
final int n=accepts.incrementAndGet();
System.out.println("accepted #"+n+" from: "+socket);
new Thread(new Runnable() {
#Override public void run() {
read(socket);
}
},"accept #"+n).start();
}
};
new Server(serverSocket,socketConsumer).start();
}
static boolean send(String host,Integer service) {
Socket socket;
try {
socket=new Socket(host,service);
OutputStreamWriter out=new OutputStreamWriter(socket.getOutputStream());
out.write("hello\n");
out.flush();
socket.close();
return true;
} catch(IOException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) throws InterruptedException {
final String host="localhost";
final Integer service=1237;
try {
So43462480 tcp=new So43462480(host,service);
} catch(Exception e) {
System.out.println("main caught: "+e);
}
for(int i=0;i<10;i++) {
boolean ok=send(host,service);
if(!ok)
System.out.println("send failed");
}
Thread.sleep(100);
for(Thread thread:Thread.getAllStackTraces().keySet())
System.out.println(thread);
}
AtomicInteger accepts=new AtomicInteger();
}
edit: a more simple solution:
import java.io.*;
import java.net.*;
import java.util.concurrent.atomic.AtomicInteger;
public class So43462480take2 {
class Server extends Thread {
Server(ServerSocket serverSocket) {
super("Server");
this.serverSocket=serverSocket;
}
#Override public void run() {
System.out.println("server running on: "+serverSocket);
while(true)
try {
Socket socket=serverSocket.accept();
final int n=accepts.incrementAndGet();
System.out.println("accepted #"+n+" from: "+socket);
new Thread(new Runnable() {
#Override public void run() {
InputStream inputStream=null;
try {
inputStream=socket.getInputStream();
BufferedReader in=new BufferedReader(new InputStreamReader(inputStream));
String string=in.readLine();
System.out.println(string+" from: "+socket);
socket.close();
System.out.println(Thread.currentThread().getName()+" succeeded");
} catch(IOException e) {
System.out.println(Thread.currentThread().getName()+" caught: "+e);
}
}
},"accept #"+n).start();
} catch(IOException e) {
System.out.println(getName()+" caught: "+e);
break;
}
}
final ServerSocket serverSocket;
}
So43462480take2(String host,Integer service) throws IOException {
serverSocket=new ServerSocket();
SocketAddress socketAddress=new InetSocketAddress(host,service);
serverSocket.bind(socketAddress);
new Server(serverSocket).start();
}
static boolean send(String host,Integer service) {
Socket socket;
try {
socket=new Socket(host,service);
OutputStreamWriter out=new OutputStreamWriter(socket.getOutputStream());
out.write("hello\n");
out.flush();
socket.close();
return true;
} catch(IOException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) throws InterruptedException, IOException {
System.out.println("start");
final String host="localhost";
final Integer service=1237;
So43462480take2 tcp=new So43462480take2(host,service);
for(int i=0;i<10;i++) {
boolean ok=send(host,service);
if(!ok)
System.out.println("send failed");
}
Thread.sleep(1000);
try {
tcp.serverSocket.close();} catch(IOException e) {
System.out.println("close caught: "+e);
}
Thread.sleep(1000);
for(Thread thread:Thread.getAllStackTraces().keySet())
System.out.println(thread);
}
final ServerSocket serverSocket;
AtomicInteger accepts=new AtomicInteger();
}
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
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.
i write a program client-server with multi threading for send - receive file. The program runs and client send and server receive. the files are created but empty new files are created
Why? please help me
class client :
import java.io.*;
import java.net.Socket;
public class Client extends Thread {
Socket socket = null;
Socket socket1 = null;
public void sendFile() throws IOException {
String host = "127.0.0.1";
String host1 = "127.0.0.2";
socket = new Socket(host, 1024);
socket1 = new Socket(host1, 1025);
File file = new File("/home/reza/Desktop/link help");
File file1 = new File("/home/reza/Desktop/hi");
long length = file.length();
long length1 = file1.length();
final byte[] bytes = new byte[(int) length];
final byte[] bytes1 = new byte[(int) length1];
FileInputStream fis = new FileInputStream(file);
FileInputStream fis1 = new FileInputStream(file1);
#SuppressWarnings("resource")
final BufferedInputStream bis = new BufferedInputStream(fis);
final BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
#SuppressWarnings("resource")
final BufferedInputStream bis1 = new BufferedInputStream(fis1);
final BufferedOutputStream out1 = new BufferedOutputStream(socket1.getOutputStream());
Thread t = new Thread(new Runnable() {
public void run()
{
while(socket.isConnected())
{
Wait2();
try {
System.out.println("ok");
int count;
while ((count = bis.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Thread t1 = new Thread(new Runnable() {
public void run() {
while(socket1.isConnected())
{
Wait2();
try {
System.out.println("ok1");
int count1;
while ((count1 = bis1.read(bytes1)) > 0) {
out1.write(bytes1, 0, count1);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t1.start();
t.start();
socket.close();
socket1.close();
}
public void Wait2()
{
try {
Thread.sleep(3000);
} catch (InterruptedException x) {
System.out.println("Interrupted!");
}
}
}
class server:
import java.io.*;
import java.net.*;
public class Server {
public Server()
{
Thread t = new Thread(new Client());
t.start();
Thread t1 = new Thread(new Client());
t1.start();
}
//#SuppressWarnings("null")
public void recivefile() throws IOException {
ServerSocket serverSocket = null;
ServerSocket serverSocket1 = null;
try {
serverSocket = new ServerSocket(1024);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
try {
serverSocket1 = new ServerSocket(1025);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number1. ");
}
Socket socket = null;
Socket socket1 = null;
InputStream is = null;
InputStream is1 = null;
FileOutputStream fos = null;
FileOutputStream fos1 = null;
BufferedOutputStream bos = null;
BufferedOutputStream bos1 = null;
int bufferSize = 0;
int bufferSize1 = 0;
try {
socket = serverSocket.accept();
socket1 = serverSocket1.accept();
} catch (IOException ex) {
System.out.println("Can't accept client connection. ");
}
try {
is = socket.getInputStream();
is1 = socket1.getInputStream();
bufferSize = socket.getReceiveBufferSize();
bufferSize1 = socket1.getReceiveBufferSize();
//bufferSize2 = socket2.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
System.out.println("file recieved");
System.out.println("Buffer size1: " + bufferSize1);
System.out.println("file recieved");
System.out.println("file recieved");
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream("/home/reza/Desktop/reza");
bos = new BufferedOutputStream(fos);
fos1 = new FileOutputStream("/home/reza/Desktop/ali");
bos1 = new BufferedOutputStream(fos1);
} catch (FileNotFoundException ex) {
System.out.println("File not found. ");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
byte[] bytes1 = new byte[bufferSize1];
int count1;
while ((count1 = is1.read(bytes1)) > 0) {
bos1.write(bytes1, 0, count1);
}
bos.flush();
bos.close();
bos1.flush();
bos1.close();
is.close();
is1.close();
socket.close();
serverSocket.close();
socket1.close();
serverSocket1.close();
}
public static void main(String[] args) throws IOException
{
System.out.println("server is run, please send file");
Server s = new Server();
s.recivefile();
}
}
client test class:
import java.io.IOException;
public class clientTest extends Thread {
public static void main(String[] args) throws IOException, InterruptedException
{
Client client = new Client();
client.sendFile();
}
}
I believe this code in the server to be your issue:
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
byte[] bytes1 = new byte[bufferSize1];
int count1;
while ((count1 = is1.read(bytes1)) > 0) {
bos1.write(bytes1, 0, count1);
}
bos.flush();
bos.close();
bos1.flush();
bos1.close();
is.close();
is1.close();
socket.close();
serverSocket.close();
socket1.close();
serverSocket1.close();
So the server has connected to the client, then it immediately checks to see if there are any bytes to read, if not it stops reading and closes the connection. If this happens faster than the client can deliver any bytes, boom, no data is received. And it WILL happend faster than the client can send data because the client is connecting THEN starting thread to send the data.
Instead, the server should read on each connection for as long as the client has maintained the connection alive. The server needs to wait for the data to be received.
Notice that in your code, the client is waiting for the server to close the connection. But how is the server supposed to know when all the data is sent? Either the client must close the connection or the client must send an EOF-type marker to the server indicating an end of the data and that it is safe to close the connection.
I have implemented a multithreaded client/server program in Java for downloading files, in which the server can concurrently serve the file to many clients by utilizing threads.
When I test the server with a single client it works fine, but when I test with ten or more clients using a shell script then the downloaded files all have different sizes, which differs from the actual size of the file on the server side.
Can anyone explain why this is happening?
Code for Server:
public class FileSend implements Runnable {
Socket sock;
String pathname;
FileSend(Socket s, String filename) {
sock = s;
pathname = System.getenv("HOME") + "/" + Main.spath + "/" + filename;
}
void send(String pathname) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, ParseException {
try {
byte[] buf = new byte[1024];
OutputStream os = sock.getOutputStream();
//PrintWriter writer = new PrintWriter(os);
BufferedOutputStream out = new BufferedOutputStream(os, 1024);
int i = 0;
File fp = new File(pathname);
RandomAccessFile ra = new RandomAccessFile(fp, "r");
long bytecount = 1024;
////////////////
while ((i = ra.read(buf, 0, 1024)) != -1) {
bytecount += 1024;
out.write(buf, 0, i);
out.flush();
}
sock.shutdownOutput();
out.close();
ra.close();
sock.close();
} catch (IOException ex) {
}
}
public void run() {
try {
try {
try {
try {
send(this.pathname);
} catch (ParseException ex) {
Logger.getLogger(FileSend.class.getName()).log(Level.SEVERE,
null, ex);
}
} catch (NoSuchPaddingException ex) {
Logger.getLogger(FileSend.class.getName()).log(Level.SEVERE,
null, ex);
}
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(FileSend.class.getName()).log(Level.SEVERE, null,
ex);
}
} catch (IOException ex) {
Logger.getLogger(FileSend.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Client Code:
public class FileRecieve implements Runnable {
Socket sock;
String path;
Date T;
//private Date d2;
FileRecieve(Socket s, String fname, Date d1) {
sock = s;
path = Main.Dpath + "/" + fname;
T = d1;
}
public void run() {
try {
byte[] b = new byte[1024];
int len = 0;
long bytcount = 1024;
File fp = new File(path);
// RandomAccessFile ra = new RandomAccessFile(fp,"r");
RandomAccessFile ra = new RandomAccessFile(fp, "rw");
ra.seek(0);
InputStream is = sock.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
while ((len = is.read(b, 0, 1024)) != -1) {
bytcount = bytcount + 1024;
//decrypt
ra.write(b, 0, len);
}
is.close();
ra.close();
sock.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Please help, many thanks in advance.
I have made a similar attempt at a Mutithreaded Client-Server file downloader app. You can check it out at code review. I have used the java.util.concurrent package classes for the multithreading bit.