I'm having trouble switching between 2 networks programmatically on a Raspberry Pi 3 running Android things (but it should be the same as running normal Android).
The first network is coming from a device server as an access point. It runs an FTP server which I need to access through its network. It has a static IP-address in the 192.168.xxx.xxx network that I know, and is secured by WPA2-PSK. I have the SSID and passphrase which I know to be correct. This device is in it's own private network that it makes itself and isn't reachable an external address. The only way to connect to it is by connecting to it's network and FTP'ing to it's static address.
The second network is an open network of which I also know the SSID. This one is preconfigured by another application, so my application can't update the configuration.
The code below is what I have at the moment. The DownloadFilesTask is called in the onCreate of my startscreen.
The configuration of the first network seems to fail, as adding the configuration to the WifiManager returns -1 as networkId as I can see in the log in the last 2 lines before disconnecting and loosing all logging. The 2 lines are:
04-11 11:10:51.258 1332-1349/rocks.androidthings.hellothings D/connecting: SSID1 passphase
04-11 11:10:51.259 411-740/system_process I/addOrUpdateNetwork: uid = 10026 SSID SSID1 nid=-1
After this I get a java.net.socketException: invalid argument or cannot connect assign requested address.
I have been struggling with this for the past few days, so any help would be appreciated.
public String connectToNetwork1() {
try {
WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.getConnectionInfo().getSSID().equals("\"" + SSID1 + "\"")) {
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + SSID1 + "\"";
conf.preSharedKey = "\"" + passphrase + "\"";
conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
Log.d("connecting", conf.SSID + " " + conf.preSharedKey);
int networkId = wifiManager.addNetwork(conf);
Log.d("after connecting", conf.SSID + " " + conf.preSharedKey);
wifiManager.disconnect();
Thread t = new Thread(() -> {
wifiManager.enableNetwork(networkId, true);
});
t.start();
t.join();
wifiManager.reconnect();
Log.d("re connecting", wifiManager.getConnectionInfo().getSSID());
return wifiManager.getConnectionInfo().toString();
} else {
Log.d("WIFI", "already connected to network1");
return "already connected to network1";
}
} catch (Exception ex) {
Log.d("ERROR", ex.toString());
}
return "nougabollen";
}
public String connectToNetwork2() {
try {
WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.getConnectionInfo().getSSID().equals("\"" + SSID2 + "\"")) {
/*WifiConfiguration conf = new WifiConfiguration(); //
conf.SSID = "\"" + SSID2 + "\""; //
//
conf.status = WifiConfiguration.Status.ENABLED; //
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); // this block is useless since my application can't update this network
// since network 2 is configured elsewhere
Log.d("connecting", conf.SSID); //
//
int networkId = wifiManager.addNetwork(conf);*/ //
int networkId = -2;
List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
for(WifiConfiguration wc : configs){
if(wc.SSID.equals("\"" + SSID2 + "\"")){
networkId = wc.networkId;
}
}
int finalNetworkId = networkId;
wifiManager.disconnect();
Thread t = new Thread(() -> {
wifiManager.enableNetwork(finalNetworkId, true);
});
t.start();
t.join();
wifiManager.reconnect();
Log.d("re connecting", wifiManager.getConnectionInfo().getSSID());
return "tried networkId: " + networkId + " " + wifiManager.getConnectionInfo().toString();
} else {
Log.d("WIFI", "already connected to network2");
return "already connected to network2";
}
} catch (Exception ex) {
Log.d("ERROR", ex.toString());
}
return "smoutebollen";
}
private class DownloadFilesTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String text = "";
text += " " + connectToNetwork1();
text += " " + retrieveFile();
text += " " + connectToNetwork2();
Log.d("text", text);
return text;
}
protected void onPostExecute(String text) {
test.setText(text);
}
}
The code that I use to retrieve the file is (using apache.commons.net):
public static String getDummyFile(){
FTPClient client = new FTPClient();
Log.d("ftp","client created");
InetAddress ip = null;
try {
ip = InetAddress.getByName("192.168.242.129"); // this is the address of the device creating the first network
}
catch (Exception e){
Log.d("inetaddres",e.toString());
}
try {
Log.d("inet", ip.getHostAddress());
int reply = -1; //response
client.connect(ip);
Log.d("ftp","client connected");
reply = client.getReplyCode();
Log.d("ftp",""+reply);
client.enterLocalPassiveMode();
Log.d("ftp","passive mode");
//check if login is accepted
/*if (!client.login("anonymous", "")) {
Log.d("FTP", "error logging in");
}*/
//check if bad reponse code
/*if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
Log.d("FTP", "connection refused");
}*/
//set file type to binary and enter passive mode, active not supported on android
client.setFileType(FTP.BINARY_FILE_TYPE);
Log.d("ftp", "set type to binary");
client.changeWorkingDirectory("/files");
Log.d("ftp","changed dir");
String[] names = client.listNames();
Log.d("FTP", names[1].toString());
Log.d("FTP", client.printWorkingDirectory() + "/" + names[1].toString());
mapFiles(client,"/files","",0);
return client.printWorkingDirectory() + "/" + names[1].toString();
} catch (Exception e) {
Log.d("ftp",e.toString());
text = e.toString();
}
finally {
try {
client.disconnect();
}
catch (Exception e){
}
}
return text;
}
which gives the exception when trying to connect, since I'm not connected to the network.
So I managed to get it working, the following is my working code. Main differences are setting WPA as protocol, and letting the thread were I connect sleep for 3 seconds after enabling the network.
public String connectToXs() {
try {
WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.getConnectionInfo().getSSID().equals("\"ssid\"")) {
WifiConfiguration wc = new WifiConfiguration();
wc.SSID = "\"ssid\"";
wc.preSharedKey = "\"key\"";
wc.status = WifiConfiguration.Status.ENABLED;
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
int res = wifiManager.addNetwork(wc);
Log.d("WifiPreference", "add Network returned " + res );
final boolean[] b = new boolean[1];
Thread t = new Thread(() -> {
b[0] = wifiManager.enableNetwork(res, true);
wifiManager.setWifiEnabled(true);
try {
Thread.sleep(3000);
}
catch (Exception e){
Log.d("ERROR",e.toString());
}
});
t.start();
t.join();
Log.d("WifiPreference", "enableNetwork returned " + b[0]);
return wifiManager.getConnectionInfo().toString();
} else {
Log.d("WIFI", "already connected");
return "already connected";
}
} catch (Exception ex) {
Log.d("ERROR", ex.toString());
}
return "nougabollen";
}
public String connectToGuest() {
try {
WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.getConnectionInfo().getSSID().equals("\"" + "ssid2" + "\"")) {
//int networkId = wifiManager.addNetwork(conf);
int networkId = -2;
List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
for(WifiConfiguration wc : configs){
if(wc.SSID.equals("\"SSID2\"")){
networkId = wc.networkId;
}
}
int finalNetworkId = networkId;
wifiManager.disconnect();
Thread t = new Thread(() -> {
wifiManager.enableNetwork(finalNetworkId, true);
try {
Thread.sleep(3000);
}
catch (Exception e){
Log.d("ERROR",e.toString());
}
});
t.start();
t.join();
wifiManager.reconnect();
Log.d("re connecting", wifiManager.getConnectionInfo().getSSID());
return "tried networkId: " + networkId + " " + wifiManager.getConnectionInfo().toString();
} else {
Log.d("WIFI", "already connected");
return "already connected";
}
} catch (Exception ex) {
Log.d("ERROR", ex.toString());
}
return "smoutebollen";
}
Related
I am trying to work with JavaOsc but I am having difficulties establishing a connection. My test code is below, but it does not matter what IP address port I put in, it appears to connect (which is not correct) and there is no response I am receiving. So I am doing something wrong, but find it hard to find documentation.
final static private int port = 10023;
final static private String ipAddess = "192.168.1.78";
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(true) {
OSCPortOut sender = null;
OSCPortIn receiver = null;
try {
//receiver = new OSCPortIn(10023);
OSCMessageListener msgListener = new OSCMessageListener() {
#Override
public void acceptMessage(OSCMessageEvent oscMessageEvent) {
System.out.println("Message received A! " + oscMessageEvent.toString());
}
};
OSCPacketListener listener = new OSCPacketListener() {
#Override
public void handlePacket(OSCPacketEvent oscPacketEvent) {
System.out.println("Package received A! " + oscPacketEvent.toString());
}
#Override
public void handleBadData(OSCBadDataEvent oscBadDataEvent) {
System.out.println("Package BAD received B!");
}
public void acceptMessage(java.util.Date time, OSCMessage message) {
System.out.println("Message received!");
}
};
MessageSelector selector = new MessageSelector() {
#Override
public boolean isInfoRequired() {
System.out.println("Info required call");
return false;
}
#Override
public boolean matches(OSCMessageEvent oscMessageEvent) {
System.out.println("Message match?? " + oscMessageEvent.toString());
return false;
}
};
receiver = new OSCPortInBuilder().addPacketListener(listener).addMessageListener(selector, msgListener).setLocalPort(port).setRemotePort(port).build();
receiver.connect();
receiver.startListening();
sender = new OSCPortOut(InetAddress.getByName(ipAddess), port);
sender.connect();
System.out.println("Remote address: " + sender.getRemoteAddress() + " local: " + sender.getLocalAddress());
List<String> vars = new ArrayList<String>();
vars.add("/info");
OSCMessage msg = new OSCMessage("/msgAddress", vars);
System.out.println("Is connected: " + sender.isConnected());
sender.send(msg);
System.out.println("Msg info: " + msg.getInfo() + " - " + msg.getAddress());
System.out.println("Deamon: " + receiver.isDaemonListener() + " is listening " + receiver.isListening() + " is connected " + receiver.isConnected());
System.out.println("Please type 'q' to stop.");
if(scanner.nextLine().equalsIgnoreCase("q")) break;
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace(System.out);
} finally {
try {
if (sender != null) sender.close();
if (receiver != null) receiver.close();
} catch (IOException e){
System.out.println("Problem closing: " + e.getMessage());
}
}
}
System.out.println("Finished.");
The response is:
Info required
Remote address: /192.168.1.78:10023 local: /0.0.0.0:0
Is connected: true
Msg info: null - /msgAddress
Deamon: true is listening true is connected true
Please type 'q' to stop.
I also tried to contact the local receiver (using 127.0.0.1) but that didn't work either.
Any suggestions would be really appreciated!
I'm currently developing an email application with a background service used in conjunction with the JavaMail Idle functionality. The background service keeps the idle functionality working by issuing a check every 29 minutes (as the server being used (Exchange server)) can sometimes drop the connection after 30 minutes of being connected.
Whilst this works perfectly, if the Exchange server is offline, then the application will continue to attempt to reconnect to the IMAP folder indefinately. I have noticed spikes in data usage between the hours of 3AM & 6AM (a typical Exchange update time).
To avoid the increased data usage, I am looking to implement functionality where the app should attempt to reconnect to the IMAP folder three times and then display a warning to the user that the server is offline and a new connection attempt will be retried in 30 minutes.
In order to achieve this, how would I be able to detect if the Exchange server is actually offline/updating & would any exceptions be thrown, if the app cannot connect to the IMAP folder? As if an exception would be thrown, then I could save a local int variable and increment it by one every time the exception is thrown and then show the alert to the user on the third time.
My current code implementation can be seen below:
public void checkInboxEmail(final String host, final String user, final String password) {
Log.d(TAG, "checkEmail");
this.host = host;
this.user = user;
this.password = password;
new Thread(new Runnable() {
#Override
public void run() {
try {
Log.d(TAG, "checkEmail - run()");
long databaseRecords;
//create properties field
Properties properties = new Properties();
properties.put("mail.store.protocol", "imaps");
properties.put("mail.imaps.ssl.trust", "*");
properties.put("mail.debug", "true");
emailSession = Session.getInstance(properties, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
});
IMAPStore imapStore = (IMAPStore) emailSession.getStore("imaps");
// imapStore.connect();
imapStore.connect(host, user, password);
if (imapStore.isConnected()) {
Log.d("MailPush", "Successfully connected to IMAP");
} else {
Log.d("MailPush", "Not connected to IMAP");
}
final IMAPFolder folder = (IMAPFolder) imapStore.getFolder("Inbox");
folder.open(IMAPFolder.READ_WRITE);
databaseRecords = dbManager.getReceivedEmailRecordsCount();
if (databaseRecords < folder.getMessageCount()) {
Log.d(TAG, "Receiving Mail...");
receiveMail(folder.getMessages());
} else {
Log.d(TAG, "Records match.");
}
Folder[] fdr = imapStore.getDefaultFolder().list();
for (Folder fd : fdr)
System.out.println(">> " + fd.getName());
folder.addMessageCountListener(new MessageCountListener() {
public void messagesAdded(MessageCountEvent e) {
System.out.println("Message Added Event Fired");
Log.d(TAG, "MESSAGE TYPE: " + e.getType());
//ADDED = 1 & REMOVED = 2
try {
Message[] messages = e.getMessages();
System.out.println("messages.length---" + messages.length);
for (Message message : messages) {
if (!message.getFlags().contains(Flags.Flag.SEEN)) {
//Message is new (hasn't been seen) > Message Details
System.out.println("---------------------------------");
System.out.println("Email Number " + (message.getMessageNumber()));
System.out.println("Subject: " + message.getSubject());
System.out.println("From: " + message.getFrom()[0]);
System.out.println("Text: " + message.getContent().toString());
String from = message.getFrom()[0].toString();
String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC));
Log.d(TAG, "CC 1: " + cc);
Address[] recipients = message.getRecipients(Message.RecipientType.CC);
cc = InternetAddress.toString(recipients);
Log.d(TAG, "CC 2: " + cc);
//Check Encryption Details > Add SEEN Flag > Add to database
checkEncryption((MimeMessage) message, from, cc);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void messagesRemoved(MessageCountEvent e) {
System.out.println("Message Removed Event fired");
}
});
folder.addMessageChangedListener(new MessageChangedListener() {
public void messageChanged(MessageChangedEvent e) {
System.out.println("Message Changed Event fired");
}
});
startListening(folder);
//close the store and folder objects
// emailFolder.close(false);
// store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private void startListening(IMAPFolder imapFolder) {
Log.d(TAG, "startListening");
// We need to create a new thread to keep alive the connection
Thread t = new Thread(
new KeepAliveRunnable(imapFolder), "IdleConnectionKeepAlive"
);
t.start();
while (!Thread.interrupted()) {
Log.d(TAG, "Starting IDLE");
try {
Log.d(TAG, "Setting IDLE");
imapFolder.idle();
} catch (FolderClosedException fex) {
//Server closes connection.
Log.d(TAG, "FolderClosedException. Server potentially dropped connection. Retrying connection...");
fex.printStackTrace();
if (!isServiceRunning(MyService.class)) {
Log.d(TAG, "Service isn't running. Starting service...");
//Start service
Intent intent = new Intent(context, MyService.class);
intent.putExtra("host", host);
intent.putExtra("email", user);
intent.putExtra("password", password);
context.startService(intent);
} else {
Log.d(TAG, "Service is already running. Checking email...");
checkInboxEmail(host, user, password);
}
} catch (MessagingException e) {
//Idle isn't supported by server.
Log.d(TAG, "Messaging exception during IDLE: ");
e.printStackTrace();
}
}
// Shutdown keep alive thread
if (t.isAlive()) {
Log.d(TAG, "Interrupting thread");
t.interrupt();
}
}
private static class KeepAliveRunnable implements Runnable {
private final String TAG = getClass().getName();
private static final long KEEP_ALIVE_FREQ = 60000 * 29; // 29 minutes (Exchange connection drops after 20-30 minutes)
private IMAPFolder folder;
KeepAliveRunnable(IMAPFolder folder) {
this.folder = folder;
}
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Thread.sleep(KEEP_ALIVE_FREQ);
// Perform a messageCount check just to keep alive the connection
Log.d(TAG, "Performing a messageCount check to keep the connection alive");
folder.getMessageCount();
} catch (InterruptedException e) {
// Ignore, just aborting the thread...
Log.d(TAG, "Interrupted...");
e.printStackTrace();
} catch (MessagingException e) {
// Shouldn't really happen...
Log.d(TAG, "Unexpected exception while keeping alive the IDLE connection");
e.printStackTrace();
}
}
}
}
private void receiveMail(Message[] messages) {
try {
System.out.println("messages.length---" + messages.length);
for (Message message : messages) {
if (!message.getFlags().contains(Flags.Flag.SEEN)) {
//Message is new (hasn't been seen) > Message Details
System.out.println("---------------------------------");
System.out.println("Email Number " + (message.getMessageNumber()));
System.out.println("Subject: " + message.getSubject());
System.out.println("From: " + message.getFrom()[0]);
System.out.println("Text: " + message.getContent().toString());
String from = message.getFrom()[0].toString();
String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC));
//Check Encryption Details > Add SEEN Flag > Add to database
checkEncryption((MimeMessage) message, from, cc);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
If the server is up but not accepting connections, the connect will fail immediately (with an exception). If the server is down, and you've set a connect timeout, the connect will fail after the timeout (with an exception).
To clarify #BillShannon's answer, if the server host is up but Exchange is not accepting connections, the connect will fail immediately with a ConnectException: connection refused. If the server host is down, the connect will fail after the timeout with a ConnectException: connect timeout (or possibly a SocketTimeoutException), regardless of whether you've set a connect timeout, as the platform always has one.
I am using smack for building a chat app in Android. I am using a sticky_service to hold the connection. I have a confusion that if my app goes to sleep what happens to TCP connection. I have read few answers on the page - How to make the Android device hold a TCP connection to Internet without wake lock?
It wakes up for a brief period of time - For smack I can think of it as the processmessage listener (http://www.programcreek.com/java-api-examples/index.php?api=org.jivesoftware.smack.MessageListener) is called. I am inserting data in db for that. Is there any guarantee that work will be complete or if the execution is left in between will it be started from there.
Hello dear you can use this code snippet :
protected void connect() {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": connecting");
features.encryptionEnabled = false;
lastConnect = SystemClock.elapsedRealtime();
lastPingSent = SystemClock.elapsedRealtime();
this.attempt++;
try {
shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER);
tagReader = new XmlReader(wakeLock);
tagWriter = new TagWriter();
packetCallbacks.clear();
this.changeStatus(Account.State.CONNECTING);
final Bundle result = DNSHelper.getSRVRecord(account.getServer());
final ArrayList<Parcelable> values = result.getParcelableArrayList("values");
if ("timeout".equals(result.getString("error"))) {
throw new IOException("timeout in dns");
} else if (values != null) {
int i = 0;
boolean socketError = true;
while (socketError && values.size() > i) {
final Bundle namePort = (Bundle) values.get(i);
try {
String srvRecordServer;
try {
srvRecordServer = IDN.toASCII(namePort.getString("name"));
} catch (final IllegalArgumentException e) {
// TODO: Handle me?`
srvRecordServer = "";
}
final int srvRecordPort = namePort.getInt("port");
final String srvIpServer = namePort.getString("ip");
final InetSocketAddress addr;
if (srvIpServer != null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
} else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
}
socket = new Socket();
socket.connect(addr, 20000);
socketError = false;
} catch (final UnknownHostException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
i++;
} catch (final IOException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
i++;
}
}
if (socketError) {
throw new UnknownHostException();
}
} else if (result.containsKey("error")
&& "nosrv".equals(result.getString("error", null))) {
//todo:change here to server.
socket = new Socket(server_ip, server port);
} else {
throw new IOException("timeout in dns");
}
final OutputStream out = socket.getOutputStream();
tagWriter.setOutputStream(out);
final InputStream in = socket.getInputStream();
tagReader.setInputStream(in);
tagWriter.beginDocument();
sendStartStream();
Tag nextTag;
while ((nextTag = tagReader.readTag()) != null) {
if (nextTag.isStart("stream")) {
processStream(nextTag);
break;
} else {
throw new IOException("unknown tag on connect");
}
}
if (socket.isConnected()) {
socket.close();
}
} catch (final UnknownHostException | ConnectException e) {
this.changeStatus(Account.State.SERVER_NOT_FOUND);
} catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage());
this.changeStatus(Account.State.OFFLINE);
} finally {
if (wakeLock.isHeld()) {
try {
wakeLock.release();
} catch (final RuntimeException ignored) {
}
}
}
}
enjoy your code:)
server will run the array which disconnect user after client press connect button
public void run() {
String message, connect = "Connect", disconnect = "Disconnect", chat = "Chat" ;
String[] data;
try {
while ((message = reader.readLine()) != null) {
outputTextArea.append("Received: " + message + "\n");
data = message.split(":");
for (String token:data) {
outputTextArea.append(token + "\n");
}
if (data[2].equals(connect)) {
tellEveryone((data[0] + ":" + data[1] + ":" + chat));
userAdd(data[0]);
} else if (data[2].equals(disconnect)) {
tellEveryone((data[0] + ":has disconnected." + ":" + chat));
userRemove(data[0]);
} else if (data[2].equals(chat)) {
tellEveryone(message);
} else {
outputTextArea.append("No Conditions were met. \n");
}
} // end while
} // end try
catch (Exception ex) {
outputTextArea.append("Lost a connection. \n");
ex.printStackTrace();
clientOutputStreams.remove(client);
} // end catch
} // end run()
} // end class ClientHandler
public void userAdd (String data) {
String message, add = ": :Connect", done = "Server: :Done", name = data;
outputTextArea.append("Before " + name + " added. \n");
onlineUsers.add(name);
outputTextArea.append("After " + name + " added. \n");
String[] tempList = new String[(onlineUsers.size())];
onlineUsers.toArray(tempList);
for (String token:tempList) {
message = (token + add);
tellEveryone(message);
}
tellEveryone(done);
}
public void userRemove (String data) {
String message, add = ": :Connect", done = "Server: :Done", name = data;
onlineUsers.remove(name);
String[] tempList = new String[(onlineUsers.size())];
onlineUsers.toArray(tempList);
for (String token:tempList) {
message = (token + add);
tellEveryone(message);
}
tellEveryone(done);
}
public void tellEveryone(String message) {
// sends message to everyone connected to server
Iterator it = clientOutputStreams.iterator();
while (it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
outputTextArea.setCaretPosition(outputTextArea.getDocument().getLength());
} // end try
catch (Exception ex) {
outputTextArea.append("Error telling everyone. \n");
} // end catch
} // end while
} // end tellEveryone()
Client Side:
ArrayList<String> userlist = new ArrayList();
public class IncomingReader implements Runnable{
public void run(){
String stream;
String[] data;
String done = "Done", connect = "connect", disconnect = "Disconnect", chat ="Chat";
try {
while ((stream = reader.readLine()) != null){
data = stream.split("!");
if (data[2].equals(chat)) {
chatTextArea.append(data[0]+":"+ data[1]+"\n");
chatTextArea.setCaretPosition(chatTextArea.getDocument().getLength());
} else if (data[2].equals(connect)){
chatTextArea.removeAll();
userAdd(data[0]);
} else if (data[2].equals(disconnect)){
userRemove(data[0]);
} else if (data[2].equals(done)){
onlineuserlist.setText("");
writeUsers();
userlist.clear();
}
}
}catch(Exception ex){
}
}
}
private void userAdd(String data) {
userlist.add(data);
}
private void userRemove(String data) {
chatTextArea.append(data +"has disconnected.\n");
}
private void writeUsers() {
String[] tempList = new String[(userlist.size())];
userlist.toArray(tempList);
for (String token:tempList) {
onlineuserlist.append(token +"\n");
}
}
public void sendDisconnect(){
String bye =(username + ": :Disconnect");
try{
writer.println(bye);
writer.flush();
} catch (Exception ex){
chatTextArea.append("could not send Disconnect Message.\n");
}
}
public void Disconnect(){
try{
chatTextArea.append("Disconnected.\n");
sock.close();
} catch (Exception ex){
chatTextArea.append("Failed to disconnect. \n");
}
isConnected = false;
usernameField.setEditable(true);
onlineuserlist.setText("");
}
}
after start the server and client press the connect button, it will show which user has connected but it also disconnect the connection and got this error.
java.lang.ArrayIndexOutOfBoundsException: 2
at chatsystemserver.ServerSide$ClientHandler.run(ServerSide.java:55)
at java.lang.Thread.run(Thread.java:745)
It would appear that you don't have an array of size == 3 when you do you split. You might want to do some array size checking before you access "data[2]".
I'm wondering if the way that I connect and disconnect to/from a FTP server is correct or if it can be better.
I'm using sun.net.ftp.FtpClient.
import sun.net.ftp.FtpClient;
public class FTPUtility
{
public static FtpClient connect(FTPConfig ftpConfig,WebTextArea statusTextArea)
{
String hostname = ftpConfig.getFtpServer();
String username = ftpConfig.getUsername();
String password = ftpConfig.getPassword();
String portnumb = ftpConfig.getPort();
try
{
FtpClient client = new FtpClient(hostname);
statusTextArea.append("Connecting to " + hostname + " as " + username + " on port:" + portnumb );
client.login(username, password);
client.binary();
statusTextArea.append("Connected to " + hostname + " as " + username + " on port:" + portnumb );
return client;
}
catch (Exception e)
{
statusTextArea.append("Failed to connect to " + hostname + " as " + username + "\n".concat(e.getMessage()) );
return null;
}
}
public static boolean disConnect(FtpClient client, WebTextArea statusTextArea)
{
boolean success = false;
if (client != null)
{
try
{
statusTextArea.append("Disconnecting from server...");
client.closeServer();
statusTextArea.append("Disconnected from server." );
success = true;
}
catch (Exception e)
{
statusTextArea.append("Failed to disconnect from server. " + "\n".concat(e.getMessage()));
}
}
return success;
}
}
If we look at the documentation it shows using logout() and disconnect()
I would also suggestion a better naming convention for your method name disConnect which should just be disconnect(FtpClient client, WebTextArea statusTextArea) (no capital C)
boolean error = false;
try {
int reply;
ftp.connect("ftp.foobar.com");
System.out.println("Connected to " + server + ".");
System.out.print(ftp.getReplyString());
// After connection attempt, you should check the reply code to verify
// success.
reply = ftp.getReplyCode();
if(!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
System.err.println("FTP server refused connection.");
System.exit(1);
}
... // transfer files
ftp.logout();
} catch(IOException e) {
error = true;
e.printStackTrace();
} finally {
if(ftp.isConnected()) {
try {
ftp.disconnect();
} catch(IOException ioe) {
// do nothing
}
}
System.exit(error ? 1 : 0);
}
Also return false if the closing fails
catch (Exception e)
{
statusTextArea.append("Failed to disconnect from server. " + "\n".concat(e.getMessage()));
return false;
}
}
You might want to check out the FtpClient from apache commons project:
FtpClient.
The javaDoc contains some well worked out examples.