Sign in to follow this  
grumpyOldDude

server exception while attempt to send file

Recommended Posts

In the previous thread I had succeeded in sending file from client to server, so i'm trying to move a step further by sending file back to client. But it crashed. When googled the crash exception - though there were different answers for as many threads - a clue I pulled out was that the client code was closing the socket while the server was trying to send. So I tried commenting out the sock.close() in client code. Though it didn't crash anymore but it didn't send file data either (which is worse so I remove the comment).

So how do I solve this? Here are the Client code, server code and crash dump;  I've placed an arrow to indicate line 55 pointed to by the exception  

Many thanks

Client code: (to simplify you can Ignore the android part of code, its only purpose is to help select a file)

public class FSendfileActivity extends Activity {
    private Socket sock;
    private static final int SELECT = 1;
    private String serverIP = "192.168.1.4";    
    private String selectedImagePath;
    private ImageView img;
    final static String puzzleGame= "pop";
    String ImageDir2Client;      
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fsendfile);

	    ImageDir2Client = Environment.getExternalStorageDirectory().getAbsolutePath();
        
        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 PGame Image data" ), SELECT );
                    }
                });
                               
        Button send = (Button) findViewById(R.id.bSend);
        final TextView status = (TextView) findViewById(R.id.tvStatus);
        
        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);
                                        
                             File myFile = new File (selectedImagePath); 
                             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);
                             Log.v(qcd, "mybytearray.length    "+mybytearray.length);
                             os.flush();
                             sock.close();                                             // CLIENT CLOSE SOCKET HERE
                              
           //=================  client receiving data ==============================
                             int filesize=2373620;
                             int bytesRead;     
                             int current = 0;
                             byte [] mybytearray2  = new byte [filesize];
                             InputStream is;
                             Long start=0l, end=0l;
                             while( ((is = sock.getInputStream()) != null) || ((end-start) < 10000) ){
                                 start = System.currentTimeMillis(); 	 
                                 FileOutputStream fos = new FileOutputStream(ImageDir2Client + "/client RootFolder/fromServer00002.jpg"); // destination path and name of file
                                 BufferedOutputStream bos = new BufferedOutputStream(fos);
                                 bytesRead = is.read(mybytearray2,0,mybytearray2.length);
                                 current = bytesRead;
                                     
                                 do {
                                    bytesRead =  is.read(mybytearray2, current, (mybytearray2.length-current));
                                    if(bytesRead >= 0) current += bytesRead;
                                 } while(bytesRead > -1);

                                 bos.write(mybytearray2, 0 , current);
                                 bos.flush();
                                 end = System.currentTimeMillis();  
                                 bos.close();                            	 
                             }
                             System.out.println("AT CLIENT:"+"  time elapsed  "+(end-start));
                        } catch (UnknownHostException e) {
                            e.printStackTrace();
                        } catch (IOException 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) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
                TextView path = (TextView) findViewById(R.id.tvPath);
                path.setText("Image Path : " + selectedImagePath);
                img.setImageURI(selectedImageUri);
                Log.v(qcd, selectedImagePath);
            }     
        }
    }

    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);
    }
}

Server code:

public class FileServer {    
                
    public static void main(String[] args) throws IOException {
        int filesize=2373620; // filesize temporary hardcoded                   
        long start = System.currentTimeMillis(); 
        int bytesRead;     
        int current = 0;     
                                
        InetAddress IP=InetAddress.getLocalHost();   
        ServerSocket servsock = new ServerSocket(57925);      
        System.out.println("IP "+IP.getHostAddress()+"  ***%% :"+servsock.getLocalPort());  
        
        while (true) {  
          System.out.println("Waiting...");           
          Socket      sock = servsock.accept();
          System.out.println("Accepted connection : " + sock);
                         
            byte [] mybytearray  = new byte [filesize];
            InputStream is = sock.getInputStream();
            FileOutputStream fos = new FileOutputStream("C:\\server RootFolder\\puzzleGame_050052z.jpg"); 
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bytesRead = is.read(mybytearray,0,mybytearray.length);
            current = bytesRead;
                
            do {
               bytesRead =  is.read(mybytearray, current, (mybytearray.length-current));
               if(bytesRead >= 0) current += bytesRead;
            } while(bytesRead > -1);

            bos.write(mybytearray, 0 , current);
            bos.flush();
            long end = System.currentTimeMillis();
//            System.out.println("milliseconds  "+(end-start));
            System.out.println("AT SERVER: bytesRead  "+bytesRead+"  current  "+current);
            bos.close();
   
//================== Server Processing starts here =====================================
            File myFile = new File ("C:\\server RootFolder\\puzzleGame_050052z.jpg"); 
            byte [] mybytearray2  = new byte [(int)myFile.length()];
            FileInputStream fis = new FileInputStream(myFile);
            BufferedInputStream bis = new BufferedInputStream(fis);
            bis.read(mybytearray2,0,mybytearray2.length);
            OutputStream os = sock.getOutputStream();
                   
            System.out.println("Sending to client...");
            os.write(mybytearray2,0,mybytearray2.length);             //<================ LINE 55
            System.out.println("mybytearray2.length    "+mybytearray2.length);            
//==================   Send Data to Client  ============================================              
//          OutputStream out = sock.getOutputStream();

 //           servsock.close();
 //           sock.close(); 
          }
    }
}


Crash 

Exception in thread "main" java.net.SocketException: Connection reset by peer: socket write error
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(Unknown Source)
	at java.net.SocketOutputStream.write(Unknown Source)
	at server.FileServer.main(FileServer.java:55)

Share this post


Link to post
Share on other sites

Yeah, I did revert back to closing socket at client code because as i said in the Original Post - when I commented out socket.close(), (the result was worse) - though it didn't crash anymore but neither the server nor client received and any data. (When socket is not close at least Server did received file)

Just to make the problem clearer:

1. client  send file to  server          --------->  works 

2. server send file back to client   ---------->  fails 

3. when I commented out the socket.close() in client code in an attempt to make (2) work, it not only still fails, it also brings down (1) with it. So not closing socket at client makes it worse

Also, I don't think you should get the input stream more than once from the socket.

Can you explain further quoting which exactly you are referring to and what you mean,

Client code or server?

At server code getInputStream was to receive from client and at client code getInputStream  was to receive data from server. so to my basic understanding atm it seem both inclusions are necessary, but i'm always ready to  be corrected 

 thanks

Share this post


Link to post
Share on other sites

Hi,

Thanks for your little note, networking forum is not visited regularly by me, so I missed the next problem :)

The error is indeed that the client closes the connection, which is something you have to catch and handle, as networks do break down while in use.

The client code "while( ((is = sock.getInputStream()) != null) || ((end-start) < 10000) ){" looks suspicious, why do have the option to open the socket for input more than once? I never did any networking in Java, the added abstraction layers make it complicated for me to understand what is happening.

I am also worried about you opening the puzzle file for write at the server, and then read, where the client blindly assumes a given file size, it seems.

I think it could be useful to output some numbers on how many bytes you expect, how many bytes you got, how many bytes you want to send, how many were sent perhaps, (although there is the network internal buffer so it doesn't say much.) Maybe you're just trying to send more data than you expect.

 

For more safety, push number of bytes to expect at the stream first, so both sides agree on how many bytes to send/receive.

Share this post


Link to post
Share on other sites

Just to reiterate the above: "Connection reset by peer" is networking talk for "The other side hung up". You need to be catching IOExceptions whenever you call .write() like that. But most importantly, you need to not close the client socket. A closed socket cannot possibly receive the data from the server. Get rid of that line and start diagnosing the actual problem.

Share this post


Link to post
Share on other sites

Another tip that's helped me alot:

If possible, never debug directly from android code.

Write a java lib that you can debug both from your computer. And write some testing code to test edge cases.

Maintaining a server development is really hard if you need to use emulators/your mobile device every time you need to test it.

Share this post


Link to post
Share on other sites

Well annoyingly day job got in the way a bit.

More experienced network programmers than I can't all be wrong, so irrespective of whether I think the output came out worse or not I have removed the socket close at the client. 

Many thanks Albert. I see what you are saying. Also what hplus0603 mentioned. I wanted to created a kind of wait.... in the client code so it won't run through, but wait until the file is received from server, but stupid of me I thought I could hold up the cycle with  getInputStream() or 10 secs (whichever comes first) in the while loop. But after a long look I see that thats a stupid way of holding up the while loop.

I'm still very much concerned though, because I think if the loop is not held up to allow the server file to arrive the code will just run through. 

The server code does this implicitly with sock = servsock.accept(); but there is no equivalent "wait code" for the client that I know of, which is why i in inadvertently used getInputStream() or 10secs in the while loop. 

I've been googling into overdrive but I still can't find examples of how to make a client side wait so I will have to split the application into 2. One for Client to send file and sever to receive and the Other for server to send and client to receive

I think it could be useful to output some numbers on how many bytes you expect, how many bytes you got, how many bytes you want to send, how many were sent perhaps, (although there is the network internal buffer so it doesn't say much.) Maybe you're just trying to send more data than you expect.   For more safety, push number of bytes to expect at the stream first, so both sides agree on how many bytes to send/receive.

Good advice, thanks for that 

 

Write a java lib that you can debug both from your computer. And write some testing code to test edge cases. Maintaining a server development is really hard if you need to use emulators/your mobile device every time you need to test it.

 

Hmm... why do I have that niggling feeling that I need to be way more experienced than I am now to do what you suggested without it taking me ages to code? From your other thread I see you have way more experience so you must be correct, but I'm thinking am I capable of writing the sort of library you mentioned, in good time? 

 

But most importantly, you need to not close the client socket. A closed socket cannot possibly receive the data from the server. Get rid of that line and start diagnosing the actual problem.

 

I was naive. In fact I made a  lot of errors. Most of the example code that come up when I google are either what I achieved already or way out of scope. In this field I can't invent my own things, I've got to see an example and follow it. That's getting harder by the day.

Share this post


Link to post
Share on other sites

The client side "wait" is the connect() call.

Once the client/server are connected, each call to read() (or recv()) will block the calling thread, until some data is available.

Many thanks for hints. Exactly what I've been hunting for

Share this post


Link to post
Share on other sites

I wanted to created a kind of wait.... in the client code so it won't run through, but wait until the file is received from server, but stupid of me I thought I could hold up the cycle with getInputStream() or 10 secs (whichever comes first) in the while loop. But after a long look I see that thats a stupid way of holding up the while loop. I'm still very much concerned though, because I think if the loop is not held up to allow the server file to arrive the code will just run through.
There is no need to deal with timing (unless you want control blocking wait for read/write, or measure speed, or handle multiple connections, or ...).

Network IO is not synchronous at all.

If you send a large file, the OS splits it all up in small packets (of size MTU, something you can find in the configuration of the network, around 1500, but smaller mtu is also possible, eg at less reliable networks). These get send out onto the network towards the destination. That takes several hops, several routers forward each packet to the next router. Not all packets are necessarily taking the same route (connections between routers may become full or go down, and packets are then rerouted), and packets may get lost or become garbled (the joys of physics or humans interacting with the communication medium).

At the receiving side, all packets are put back in the right sequence again, missing packets are requested again from the sender (so yeah, double packets may happen too if a lost packet appears just to be late), and the data is given to the application. This is why you read in small pieces at the receiving end, data arrives in small pieces of unknown size (different sub-networks may use different mtu), the kernel has no large storage for the data, and it doesn't know how much is coming, nor when.

All this is handled transparently by the TCP network stacks at both sides. You can simply write data, and at the receiving end, the same data comes out, albeit at an unknown later time. All the stuff behind the read and write also make that these calls are slow. This is 'fixed' by the kernel, by blocking the call. That blocking can last forever, although network interfaces can be configured to disconnect after some time (I think, never looked into that.)

As a result there is no "too early" or "too late" in a transfer like you do. Just do a read or a write, and the kernel will handle timing and block the calls as needed. The only relevant thing is that the sender and receiver agree on how to talk to each other, and what messages actually mean. That is however all already defined in the code.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this