0

[Editing to explain this posted question is not a duplicate of the quoted question::

  1. 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

  2. In the first answer, EJP said "You are reading the socket until read() returns -1." I did not do this in my code

  3. 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

  4. 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.

  5. 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.

  6. 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);
    } 
}
  • There are too numerous problems with your code to mention. See my answer in the duplicate for the right way to do this. – user207421 Apr 18 '17 at 12:38
  • @EJP please look at the edit in the Original Post. The quoted question that is said to be a duplicate of this thread and your solutions in that thread do not solve my own code's problems in anyway. I don't think its fair just closing threads like this by approximating a previous thread to another one when the solution for the previous one does not solve the current one. – metal_jack Apr 18 '17 at 16:43
  • You mean you prefer your non-working code to working code? – user207421 Apr 18 '17 at 21:33
  • @EJP The target of what someone is doing matters! If I copy some else code because it works better, what good does it do if it doesn't fit to what my project has to achieve? The fact that one says this is a server code and another says this a server code, doesn't mean one fit to the other. More importantly this is not a popularity game. I do integrate peoples code into mine when it aligns with mine. And I have done this a lot in the past. – metal_jack Apr 18 '17 at 21:58
  • @EJP Did you read the edit at all OR you just want to close a thread to show off that you have the power to do so. When i have shown you reasons why i don't gain anything from the previous thread? Whats your aim really? – metal_jack Apr 18 '17 at 21:58
  • @EJP more so my code doesn't fail entirely. I probably just need a little tweak to perfect it and thats what I'm aiming to learn – metal_jack Apr 18 '17 at 22:02
  • @EJP you are doing a huge disservice to stackoverflow. If you don't want to help people at least don't stop others from helping. By wrongly closing a thread, when I have clearly shown how the question and the solution in the previous thread doesn't help me, you're in essence saying "I don't care and i will also stop others from helping" – metal_jack Apr 18 '17 at 22:29
  • @metal_jack - I think you misunderstand the purpose of StackOverflow. Read this [The goal of StackOverflow is not to teach you programming](https://meta.stackoverflow.com/a/292176/139985). Yes ... EJP did a disservice to >>you<< ... but not to StackOverflow. Basically, your expectation that we (collectively) are here to provide you with a free tutorial service are ... ill-founded. – Stephen C Apr 19 '17 at 03:06
  • @metal_jack - And if you want an "official" source. Read the first paragraph of the [StackOverflow Tour](http://stackoverflow.com/tour) – Stephen C Apr 19 '17 at 03:11
  • @StephenC No I have not misunderstood Stack Overflow. I am not expecting Stack Overflow to teach me programming or be a tutorial for me. All I was saying the question that was tag as duplicate is in no way the same as mine. The question solved is different from the question I asked – metal_jack Apr 19 '17 at 03:31
  • @StephenC Point out to me how that question is the same as mine. There is no overlap and the problems are different. I guess you people are covering for each other but if you want to discuss this objectively, point to me how solution to a different question would answer my question. Simply because server is mentioned ? – metal_jack Apr 19 '17 at 03:36
  • If your question is not a duplicate, then it is Too Broad ... because it requires too much effort to answer (to your satisfaction!) But I think it is a duplicate *in the sense that the StackOverflow community interprets that*. It would solve the problem of how to download multiple files. It doesn't explain your particular problems / how to fix your code, but the purpose of StackOverflow is not to solve your problems. – Stephen C Apr 19 '17 at 03:42
  • @StephenC you can either choose to discuss this objectively of blindly side with EJP If you choose to do the former maybe I can learn something. What is Stack Overflow for? I was expecting free tutorial. From my understanding its a Q&A forum. – metal_jack Apr 19 '17 at 03:45
  • @StephenC My question was specific enough. I have seen very similar questions answer numerous times. Read my edit before you add any more comments. The PROBLEM IS DIFFERENT. THE SOLUTION GIVEN WAS NEVER A PROBLEM IN MY CODE. You can go on blindly siding with your fellow ... or be objective and follow the facts! – metal_jack Apr 19 '17 at 03:53
  • 1) Don't assume that people who disagree with you are wrong. 2) Your expectations are wrong. 3) We have given you an answer to your question. The answer is ... write your code differently. 4) Don't shout at me. This is my last response on this topic. – Stephen C Apr 19 '17 at 03:53
  • @StephenC I'm not surprised its going to be your last response. You always talked broadly and never pointed out why a different question would answer mine. I never assumed you were wrong because you disagreed with me. All I said HOW IS MY QUESTION A DUPLICATE OF A DIFFERENT QUESTION. and HOW DOES A SOLUTION THAT WAS NEVER A PROBLEM FOR ME HELP ME. My expectation was never too high, its a Q&A forum – metal_jack Apr 19 '17 at 04:06

1 Answers1

0

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();
}
Ray Tayek
  • 9,841
  • 8
  • 50
  • 90
  • Does this solution solve the occasional permanent blocking? – metal_jack Apr 18 '17 at 17:14
  • it will tell you which of the accepts are hanging. – Ray Tayek Apr 18 '17 at 18:40
  • I really need a fix to stop the accepts from hanging, not just to know which accepts are hanging but also which code can fix it?. If this thread is re-opened can you provide an answer with some code snippet on how to do this. Thanks – metal_jack Apr 18 '17 at 18:50
  • see added code sample – Ray Tayek Apr 18 '17 at 19:21
  • I have spent a long while trying to understand this code you posted so I can integrate it but there are no comments at all and I don't know what many parts of the code are doing. I don't even think the objective is the same as mine. I am a beginner in client server coding. And what I am aiming for is not multiple sends and receives, but linearly one at a time. The fact remains I don't understand the code you posted at all. Mine is a very simple one (on purpose) – metal_jack Apr 18 '17 at 22:15
  • sorry for the confusion. i added a second version that you may find easier to grok. – Ray Tayek Apr 19 '17 at 17:01
  • my code just sends one string at a time. they might overlap due to the threading. the purpose of the threading is just to let you see where things hang. – Ray Tayek Apr 19 '17 at 17:03
  • Many thanks!!! Your second code is much simpler and I can even learn beyond what I was originally aiming to achieve from it. Threading was missing from my server-side code so its inclusion in your code and the better structure of your code is a big PLUS. As I learn from it if I have any questions I will pop it here. Thanks – metal_jack Apr 19 '17 at 18:53
  • android is pretty screwy in a number of ways. i would get the client server code running solid on plain old java first. this reduced my debugging time. – Ray Tayek Apr 19 '17 at 19:24