BlackBerry Forums Support Community               

Closed Thread
 
LinkBack Thread Tools
Old 09-16-2005, 04:47 PM   #1 (permalink)
Knows Where the Search Button Is
 
timinator's Avatar
 
Join Date: Jul 2005
Location: Washington
Model: 8300
Carrier: AT&T
Posts: 29
Post Thanks: 0
Thanked 0 Times in 0 Posts
Default Issues with FTP?

Please Login to Remove!

Ok, I'm trying to write a small demo app for showing how to talk to an ftp server. However, I'm running into issues. I'm fairly new to the BB api's. This demo is derived from the socket demo. When I establish the connection, I get a valid response. However, the second time through the Exchange routine, the app bombs. I posted this on the Blackberry (RIM) site as well but haven't received any replies. From what I've seen in other posts, there are some issues with the socket connection api. Is this true? Any ideas? Once I get this working then I'll repost the sample here.

Here's my current source:
Code:
/*
 * ftpTest.java
 * Adapted from the rim socketdemo
 * Demonstrates how to connect to a ftp site
 */

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import net.rim.device.api.i18n.*;
import java.io.*;
import javax.microedition.io.*;

// ftpTest.java Class --------------------------------------------------------------------------
public class ftpTest extends net.rim.device.api.ui.UiApplication implements FieldChangeListener
{
    private LabelField appTitle;                            //application title label
    private ButtonField connectButton;                      //define the buttons
    private static String host = "socket://www.yourftpserver.com:21"; //put your ftp server name here
    //private static String url;
    private boolean isRunning;
    private StringBuffer message = new StringBuffer();
    private RichTextField rtf = new RichTextField();
    
    public static void main(String[] args) {
        ftpTest TIinstance = new ftpTest();                 //create an instance of this class app
        TIinstance.enterEventDispatcher();                  //define a handle for the event processor
    }
    
    private ftpTest() {
        MainScreen ftpScreen = new MainScreen();            //create screen instance
        appTitle = new LabelField("FTP Tester");            //define app title
        connectButton = new ButtonField("Connect");         //define button titles
        connectButton.setChangeListener(this);              //define the button handles for the event processor
        ftpScreen.setTitle(appTitle);                       //post the screen title
        ftpScreen.add(connectButton);                       //post the buttons on the screen
        ftpScreen.add(rtf);                                 //post the rich text field on the screen
        pushScreen(ftpScreen);                              //post the screen itself
    }

    public void fieldChanged(Field field, int context) { //respond to button events    
        if (field == connectButton) { //if Connect button selected
             synchronized(getLockObject()) {
                if (!isRunning) {
                     isRunning = true;
                     new ConnectThread().start();
                }
            }
        }
    }
    
    private class ConnectThread extends Thread {
        private InputStreamReader inStream;
        private OutputStreamWriter outStream;
        private String rVal; //ftp result
        private int rLen; //length of ftp result
        private String rCode; //ftp reply code
        private boolean bWereIn; //true if login passed
        private boolean inProcess; //true while processing ftp session
        private String CRLF = String.valueOf(Short.parseShort("0d",16) + Short.parseShort("0a",16)); 
        private int eCode;
        
        private void exchange(String data) throws IOException {
            int length = data.length(); //cache locally for better performance
            int rlength = 255; //ftp reply
            char[] input = new char[rlength]; //input array
            rLen = 0; //reinit
            outStream.write(data, 0, length); //init the data array
            if (inStream.ready()) {
                for (int i = 0; i<rlength; ++i) { //loop through the array
                    input[i] = (char)inStream.read(); //read a char into the array
                    if (input[i] == Short.parseShort("0d", 16)) { //is CR?
                        rLen = i; //get length of result
                        if (rLen > 0) {
                            inProcess = true;
                        } else {
                            inProcess = false;
                        }
                        
                        break;
                    }
                }
            }
            StringBuffer s = new StringBuffer(); //build string buffer for display
            s.append("Received: ");
            s.append(input, 0, rlength);
            updateDisplay(s.toString());
            rVal = String.valueOf(input).substring(0,rLen);
        }
        
        public void run() {
            StreamConnection connection = null;
            try {
                updateDisplay("Starting...");
                connection = (StreamConnection)Connector.open(host); //establish connection
                updateDisplay("Connected.");
                inStream = new InputStreamReader(connection.openInputStream()); //init inbound stream
                outStream = new OutputStreamWriter(connection.openOutputStream()); //init outbound stream
                char[] input = new char[1024];
                exchange("STAT");
                
                while (inProcess) {
                    rCode = rVal.substring(0,3); //get first 3 chars for the ftp reply code
                    switch(Integer.parseInt(rCode)) {
                        case 220: { //ready for new user
                            exchange("USER userid"); //send user id
                            break;
                        }
                        case 331: { //user id okay, ready for password
                            exchange("PASS password"); //send password
                            break;
                        }
                        case 230: { //user logged in, proceed
                            exchange("QUIT"); //quit the session
                            inProcess = false; //end the ftp process
                            break;
                        }
                    }
                }
                
                inStream.close();
                outStream.close();
                connection.close();
                updateDisplay("Completed");
            } catch (IOException e) {
                System.err.println(e.toString());
                updateDisplay(e.toString());
            }
            synchronized(getLockObject()) {
                isRunning = false;
            }
        }
    }
    protected void onExit() {}
    
    private void updateDisplay(final String msg) {
        invokeLater(new Runnable() {
            public void run() {
                message.append(msg);
                message.append('\n');
                rtf.setText(message.toString());
            }
        });
    }
    
    private Object getLockObject() {
        return this;
    }
}
__________________
===================================
"There are 10 types of people in the world.
Those that understand binary and those that don't!"
www.timothytrimble.info - The ART of S/W Development
==================================
Offline  
Old 10-06-2005, 04:02 PM   #2 (permalink)
Thumbs Must Hurt
 
Join Date: Apr 2005
Location: Portland, OR., USA
Model: 9800
Carrier: AT&T
Posts: 82
Post Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Tim

I have successfully implemented most all of the FTP functions for an app I am working on for a BB 7290. It is possible and there is no show stoppers with the BB api's that affect me.

I see that your are looping your read looking for EOL characters. You should loop until -1. That's probably why your app is stopping; likely it got to the end (-1) but you keep reading looking for a EOL. It would probably timout if you let it wait.

Don't use the .ready(). That one I believe is buggy. You cannot depend on it.

Also, you want to specify your connection to be "deviceside=true". IE...
String url = "socket://" + remoteHost + ":" + controlPort + ";deviceside=true" ;
This will allow the device to work without BES/MDS. Furthermore, you may need to set the APN. This is in the Options, in the TCP section. There is section on this forum (General area) with FAQ. It lists various APN settings.

Regards,
Eric
Offline  
Old 10-17-2005, 01:59 PM   #3 (permalink)
New Member
 
Join Date: Oct 2005
Model: 7290
Posts: 1
Post Thanks: 0
Thanked 0 Times in 0 Posts
Default

I've also had problems with the ready() method. What is the work around for the "buggy" ready() method? How can you write an application that reads and write via a socket without a ready()? This is a real problem for me. It appears the RIM implementation of MIDP 2.0 is not ready (pardon the play on words) for release.

I've found the RIM JRE's read method (InputeStreamReader class) blocks when bytes are available to read, and the ready method doesn't work. Forgive me, but this is very frustrating. I've implemented our Java client application in J2SE, J2ME CDC, and CLDC MIDP, and I've never struggled with a Java API like I have with RIM's. Iím very disappointed.
Offline  
Old 10-27-2005, 04:08 PM   #4 (permalink)
Thumbs Must Hurt
 
Join Date: Apr 2005
Location: Portland, OR., USA
Model: 9800
Carrier: AT&T
Posts: 82
Post Thanks: 0
Thanked 0 Times in 0 Posts
Default

I haven't had issues where the read would block when data is present. There are a couple of pitfalls, as I mentioned in previous email. Set the deviceside=true if your not using BES. Also, you need to set APN value for socket connections.

Regards,
Eric
Offline  
Old 11-02-2005, 12:17 PM   #5 (permalink)
Thumbs Must Hurt
 
Join Date: Apr 2005
Location: Portland, OR., USA
Model: 9800
Carrier: AT&T
Posts: 82
Post Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi jaretts,

I was re-reading over my messages and I remember something I forgot when I replied to your post before.

Yes, I did have blocking issues when I knew data was ready. The situation occurred for me when opening the second FTP socket connection for the data connection. After sending the ftp GET request, there would be return data in both the command and data connections available, however the command connection was blocked and would not let me ready the GET response code. The data connection was readable.

Anyways, these issues went away after I started using the deviceside=true along with specifying the APN values in the TCP options.

I still have occasionaly issue with getting a Malformed or Bad DNS exception when attempting the connection. This only goes away with a device power cycle or turning the radio off/on. I think this is a OS bug.

Are you getting yours to work now?

Cheers,
Eric
Offline  
Closed Thread


Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On





Copyright © 2004-2014 BlackBerryForums.com.
The names RIM © and BlackBerry © are registered Trademarks of BlackBerry Inc.