I'm using the Bluecove library to devolep an Obex ftp client/server on android 2.X.
So far i managed to connect as a client from android to a pc.
I tried the bluecove example code for a server but doesn't work.
Is it possible to develop a server on android 2.X. Does any one have the code to do it.
Thank you.
public class OBEXServer implements Runnable {
private SessionNotifier serverConnection;
private boolean isStoped = false;
private boolean isRunning = false;
public final UUID OBEX_OBJECT_PUSH = new UUID(0x1105);
public static final String SERVER_NAME = "OBEX Object Push";
private UserInteraction interaction;
private OBEXServer(UserInteraction interaction) {
this.interaction = interaction;
}
public static OBEXServer startServer(UserInteraction interaction) {
OBEXServer srv = new OBEXServer(interaction);
Thread thread = new Thread(srv);
thread.start();
while (!srv.isRunning && !srv.isStoped) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new Error(e);
}
}
if (!srv.isRunning) {
throw new Error("Can't start server");
}
return srv;
}
/*
* (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
isStoped = false;
LocalDevice localDevice;
try {
localDevice = LocalDevice.getLocalDevice();
if (!localDevice.setDiscoverable(DiscoveryAgent.GIAC)) {
Logger.error("Fail to set LocalDevice Discoverable");
}
serverConnection = (SessionNotifier) Connector.open("btgoep://localhost:" + OBEX_OBJECT_PUSH + ";name="
+ SERVER_NAME);
} catch (Throwable e) {
Logger.error("OBEX Server start error", e);
isStoped = true;
return;
}
try {
ServiceRecord record = localDevice.getRecord(serverConnection);
String url = record.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
Logger.debug("BT server url: " + url);
final int OBJECT_TRANSFER_SERVICE = 0x100000;
try {
record.setDeviceServiceClasses(OBJECT_TRANSFER_SERVICE);
} catch (Throwable e) {
Logger.debug("setDeviceServiceClasses", e);
}
DataElement bluetoothProfileDescriptorList = new DataElement(DataElement.DATSEQ);
DataElement obbexPushProfileDescriptor = new DataElement(DataElement.DATSEQ);
obbexPushProfileDescriptor.addElement(new DataElement(DataElement.UUID, OBEX_OBJECT_PUSH));
obbexPushProfileDescriptor.addElement(new DataElement(DataElement.U_INT_2, 0x100));
bluetoothProfileDescriptorList.addElement(obbexPushProfileDescriptor);
record.setAttributeValue(0x0009, bluetoothProfileDescriptorList);
final short ATTR_SUPPORTED_FORMAT_LIST_LIST = 0x0303;
DataElement supportedFormatList = new DataElement(DataElement.DATSEQ);
// any type of object.
supportedFormatList.addElement(new DataElement(DataElement.U_INT_1, 0xFF));
record.setAttributeValue(ATTR_SUPPORTED_FORMAT_LIST_LIST, supportedFormatList);
final short UUID_PUBLICBROWSE_GROUP = 0x1002;
final short ATTR_BROWSE_GRP_LIST = 0x0005;
DataElement browseClassIDList = new DataElement(DataElement.DATSEQ);
UUID browseClassUUID = new UUID(UUID_PUBLICBROWSE_GROUP);
browseClassIDList.addElement(new DataElement(DataElement.UUID, browseClassUUID));
record.setAttributeValue(ATTR_BROWSE_GRP_LIST, browseClassIDList);
localDevice.updateRecord(record);
} catch (Throwable e) {
Logger.error("Updating SDP", e);
}
try {
int errorCount = 0;
int count = 0;
isRunning = true;
while (!isStoped) {
RequestHandler handler = new RequestHandler();
try {
count++;
Logger.debug("Accepting OBEX connections");
handler.connectionAccepted(serverConnection.acceptAndOpen(handler));
} catch (InterruptedIOException e) {
isStoped = true;
break;
} catch (Throwable e) {
if ("Stack closed".equals(e.getMessage())) {
isStoped = true;
}
if (isStoped) {
return;
}
errorCount++;
Logger.error("acceptAndOpen ", e);
continue;
}
errorCount = 0;
}
} finally {
close();
Logger.debug("OBEX Server finished!");
isRunning = false;
}
}
public void close() {
isStoped = true;
try {
if (serverConnection != null) {
serverConnection.close();
}
Logger.debug("OBEX ServerConnection closed");
} catch (Throwable e) {
Logger.error("OBEX Server stop error", e);
}
}
private static File homePath() {
String path = "bluetooth";
boolean isWindows = false;
String sysName = System.getProperty("os.name");
if (sysName != null) {
sysName = sysName.toLowerCase();
if (sysName.indexOf("windows") != -1) {
isWindows = true;
path = "My Documents";
}
}
File dir;
try {
dir = new File(System.getProperty("user.home"), path);
if (!dir.exists()) {
if (!dir.mkdirs()) {
throw new SecurityException();
}
}
} catch (SecurityException e) {
dir = new File(new File(System.getProperty("java.io.tmpdir"), System.getProperty("user.name")), path);
}
if (isWindows) {
dir = new File(dir, "Bluetooth Exchange Folder");
}
if (!dir.exists()) {
if (!dir.mkdirs()) {
return null;
}
} else if (!dir.isDirectory()) {
dir.delete();
if (!dir.mkdirs()) {
return null;
}
}
return dir;
}
private void showStatus(final String message) {
interaction.showStatus(message);
}
private class RequestHandler extends ServerRequestHandler {
Timer notConnectedTimer = new Timer();
boolean isConnected = false;
boolean receivedOk = false;
Connection cconn;
void connectionAccepted(Connection cconn) {
Logger.debug("Received OBEX connection");
showStatus("Client connected");
this.cconn = cconn;
if (!isConnected) {
notConnectedTimer.schedule(new TimerTask() {
public void run() {
notConnectedClose();
}
}, 1000 * 30);
}
}
void notConnectedClose() {
if (!isConnected) {
Logger.debug("OBEX connection timeout");
try {
cconn.close();
} catch (IOException e) {
}
if (!receivedOk) {
showStatus("Disconnected");
}
}
}
public int onConnect(HeaderSet request, HeaderSet reply) {
isConnected = true;
notConnectedTimer.cancel();
Logger.debug("OBEX onConnect");
return ResponseCodes.OBEX_HTTP_OK;
}
public void onDisconnect(HeaderSet request, HeaderSet reply) {
Logger.debug("OBEX onDisconnect");
if (!receivedOk) {
showStatus("Disconnected");
}
}
public int onSetPath(HeaderSet request, HeaderSet reply, boolean backup, boolean create) {
Logger.debug("OBEX onSetPath");
return super.onSetPath(request, reply, backup, create);
}
public int onDelete(HeaderSet request, HeaderSet reply) {
Logger.debug("OBEX onDelete");
return super.onDelete(request, reply);
}
public int onPut(Operation op) {
Logger.debug("OBEX onPut");
try {
HeaderSet hs = op.getReceivedHeaders();
String name = (String) hs.getHeader(HeaderSet.NAME);
if (name != null) {
Logger.debug("name:" + name);
showStatus("Receiving " + name);
} else {
name = "xxx.xx";
showStatus("Receiving file");
}
Long len = (Long) hs.getHeader(HeaderSet.LENGTH);
if (len != null) {
Logger.debug("file lenght:" + len);
interaction.setProgressValue(0);
interaction.setProgressMaximum(len.intValue());
}
File f = new File(homePath(), name);
FileOutputStream out = new FileOutputStream(f);
InputStream is = op.openInputStream();
int received = 0;
while (!isStoped) {
int data = is.read();
if (data == -1) {
Logger.debug("EOS received");
break;
}
out.write(data);
received++;
if ((len != null) && (received % 100 == 0)) {
interaction.setProgressValue(received);
}
}
op.close();
out.close();
Logger.debug("file saved:" + f.getAbsolutePath());
showStatus("Received " + name);
receivedOk = true;
return ResponseCodes.OBEX_HTTP_OK;
} catch (IOException e) {
Logger.error("OBEX Server onPut error", e);
return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
} finally {
Logger.debug("OBEX onPut ends");
interaction.setProgressDone();
}
}
public int onGet(Operation op) {
Logger.debug("OBEX onGet");
try {
HeaderSet hs = op.getReceivedHeaders();
String name = (String) hs.getHeader(HeaderSet.NAME);
return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
} catch (IOException e) {
Logger.error("OBEX Server onGet error", e);
return ResponseCodes.OBEX_HTTP_UNAVAILABLE;
} finally {
Logger.debug("OBEX onGet ends");
}
}
public void onAuthenticationFailure(byte[] userName) {
Logger.debug("OBEX AuthFailure " + new String(userName));
}
}
}
Related
This is the SocketServer code that generates a server thread
public class ProcessorCorresponder {
protected final static Logger logger = LogManager.getLogger( ProcessorCorresponder.class );
private static int port = Integer.parseInt(PropertiesLoader.getProperty("appserver.port") == null ? "666" : PropertiesLoader.getProperty("appserver.port"));
private static int maxConnections = Integer.parseInt(PropertiesLoader.getProperty("appserver.maxconnections") == null ? "666" : PropertiesLoader.getProperty("appserver.maxconnections"));
public static void main(String[] args) {
logger.info("Starting server .. "
+ "[port->" + port
+ ",databaseName->" + databaseName + "]");
try (ServerSocket listener = new ServerSocket();) {
listener.setReuseAddress(true);
listener.bind(new InetSocketAddress(port));
Socket server;
int i = 0;
while((i++ < maxConnections) || (maxConnections == 0)) {
server = listener.accept();
logger.debug(
"New Thread listening on " + server.getLocalAddress().toString() + ":" + server.getLocalPort()
+ ", initiated from IP => " + server.getInetAddress().toString() + ":" + server.getPort()
);
MySocketServer socSrv = new MySocketServer (server);
Thread t = new Thread( socSrv );
t.start();
}
} catch (Exception ex) {
logger.error("Error in ProcessorInterface", ex);
}
}
}
Server code: This is a thread to handle one connection, there is a program that monitors a serversocket and spins off request threads as needed.
public class MySocketServer implements Runnable {
protected final static Logger logger = LogManager.getLogger(MySocketServer.class);
private final Socket server;
// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;
private StringBuffer buffHeartbeatMessage = new StringBuffer().append((char) 0).append((char) 0).append((char) 0)
.append((char) 0).append((char) 0).append((char) 0);
private Heartbeat heartbeat = new Heartbeat(/* 60 */3000, buffHeartbeatMessage.toString());
public MySocketServer(Socket server) {
this.server = server;
}
#Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(this.server.getInputStream()));
BufferedOutputStream out = new HeartbeatBufferedOutputStream(this.server.getOutputStream(),
heartbeat)) {
final StreamListener listener = new StreamListener(in);
listener.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getID() == ActionEvent.ACTION_PERFORMED) {
if (event.getActionCommand().equals(StreamListener.ERROR)) {
logger.error("Problem listening to stream.");
listener.setShouldContinue(false);
stopRunning();
} else {
String messageIn = event.getActionCommand();
if (messageIn == null) { // End of Stream;
stopRunning();
} else { // hey, we can do what we were meant for
logger.debug("Request received from client");
// doing stuff here
...
// done doing stuff
logger.debug("Sending Client Response");
try {
sendResponse(opResponse, out);
} catch (Exception ex) {
logger.error("Error sending response to OP.", ex);
}
}
}
}
}
});
listener.start();
while (shouldContinue) {
// loop here until shouldContinue = false;
// this should be set to false in the ActionListener above
}
heartbeat.setShouldStop(true);
return;
} catch (Exception ex) {
logger.error("Error in ESPSocketServer", ex);
return;
}
}
private void stopRunning() {
shouldContinue = false;
}
private void sendResponse(ClientResponse opResponse, BufferedOutputStream out) throws Exception {
logger.debug("Before write");
out.write(opResponse.getResponse().getBytes());
logger.debug("After write. Before flush");
out.flush();
logger.debug("After flush");
// this log message is in my logs, so I know the message was sent
}
}
My StreamListener class.
public class StreamListener extends Thread {
protected final static Logger logger = LogManager.getLogger(StreamListener.class);
public final static String ERROR = "ERROR";
private BufferedReader reader = null;
private List<ActionListener> actionListeners = new ArrayList<>();
private boolean shouldContinue = true;
public StreamListener(BufferedReader reader) {
this.reader = reader;
}
#Override
public void run() {
while (shouldContinue) {
String message;
try {
// client blocks here and never receives message
message = reader.readLine();
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, message);
fireActionPerformed(event);
} catch (IOException e) {
e.printStackTrace();
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ERROR);
fireActionPerformed(event);
}
}
}
public void setShouldContinue(boolean shouldContinue) {
this.shouldContinue = shouldContinue;
}
public boolean getShouldContinue() {
return shouldContinue;
}
public boolean addActionListener(ActionListener listener) {
return actionListeners.add(listener);
}
public boolean removeActionListener(ActionListener listener) {
return actionListeners.remove(listener);
}
private void fireActionPerformed(ActionEvent event) {
for (ActionListener listener : actionListeners) {
listener.actionPerformed(event);
}
}
}
My Heartbeat class
public class Heartbeat extends Thread {
private BufferedOutputStream bos = null;
private int beatDelayMS = 0;
private String message = null;
private boolean shouldStop = false;
public Heartbeat(int beatDelayMS, String message) {
this.beatDelayMS = beatDelayMS;
this.message = message;
setDaemon(true);
}
#Override
public void run() {
if (bos == null) { return; }
while(!shouldStop) {
try {
sleep(beatDelayMS);
try {
bos.write(message.getBytes());
bos.flush();
} catch (IOException ex) {
// fall thru
}
} catch (InterruptedException ex) {
if (shouldStop) {
return;
}
}
}
}
public void setBufferedOutputStream(BufferedOutputStream bos) {
this.bos = bos;
}
public BufferedOutputStream getBufferedOutputStream() {
return bos;
}
public void setShouldStop(boolean shouldStop) {
this.shouldStop = shouldStop;
}
public boolean getShouldStop() {
return shouldStop;
}
}
My HeartbeatBufferedOutputStream
public class HeartbeatBufferedOutputStream extends BufferedOutputStream {
private Heartbeat heartbeat = null;
public HeartbeatBufferedOutputStream(OutputStream out, Heartbeat heartbeat) {
super(out);
this.heartbeat = heartbeat;
this.heartbeat.setBufferedOutputStream(this);
heartbeat.start();
}
#Override
public synchronized void flush() throws IOException {
super.flush();
heartbeat.interrupt();
}
}
And finally here is the "Client" class
public class Mockup extends Thread {
protected final static Logger logger = LogManager.getLogger(Mockup.class);
// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;
public static void main(String[] args) {
new Mockup().start();
}
#Override
public void run() {
try (Socket socket = new Socket("localhost", 16100);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
final StreamListener listener = new StreamListener(in);
listener.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getID() == ActionEvent.ACTION_PERFORMED) {
if (event.getActionCommand().equals(StreamListener.ERROR)) {
logger.error("Problem listening to stream.");
listener.setShouldContinue(false);
stopRunning();
} else {
String messageIn = event.getActionCommand();
if (messageIn == null) { // End of Stream;
stopRunning();
} else { // hey, we can do what we were meant for
// convert the messageIn to an OrderPower request, this parses the information
logger.info("Received message from server. [" + messageIn + "].");
}
}
}
}
});
listener.start();
StringBuffer buff = new StringBuffer("Some message to send to server");
logger.info("Sending message to server [" + buff.toString() + "]");
out.write(buff.toString().getBytes());
out.flush();
boolean started = false;
while (shouldContinue) {
if (!started) {
logger.debug("In loop");
started = true;
}
// loop here until shouldContinue = false;
// this should be set to false in the ActionListener above
}
logger.info("Exiting Mockup");
return;
} catch (Exception ex) {
logger.error("Error running MockupRunner", ex);
}
}
private void stopRunning() {
shouldContinue = false;
}
}
I have confirmed from logging messages that the Server sends a message to the BufferedOutputStream, and is flushed, but the Client logs indicate that it is blocked on the reader.readLine() and never gets the message.
You are reading lines but you are never writing lines. Add a line terminator to what you send.
I have a music player that downloads a directory from the FTP server to the SD card. And the player downloads and accepts server settings (there are two versions of ME and CE), but it happens after downloading the application crashes. When I delete some folders after downloading it works normally in ME mode, but when I download it and it takes the CE mode all the time the application crashes.
public class FTPManager {
public static final String LOG_TAG = FTPManager.class.getName();
private static final String HOST = "*******";
private static final String LOGIN = "*******";
private static final String PASSWORD = "*******";
private static final int REPEAT_TIMEOUT_MILLIS = 5 * 1000;
private int mCommandAttempts;
private String host;
private String login;
private String password;
private FTPClient mFtpClient;
private FTPManager(String host, String login, String password) {
this.host = host;
this.login = login;
this.password = password;
mFtpClient = new FTPClient();
}
public FTPManager() {
this(HOST, LOGIN, PASSWORD);
}
public boolean connect() {
mCommandAttempts = 5;
return attemptConnect();
}
private boolean attemptConnect() {
try {
mFtpClient.connect(host);
mFtpClient.login(this.login, password);
mFtpClient.setPassive(true);
} catch (Exception e) {
Log.e(LOG_TAG, e.toString());
try {
TimeUnit.MILLISECONDS.sleep(REPEAT_TIMEOUT_MILLIS);
} catch (InterruptedException e1) {
Log.e(LOG_TAG, e.toString());
return false;
}
mCommandAttempts--;
if (mCommandAttempts > 0) {
return attemptConnect();
}
}
return true;
}
public List<String> listFiles() {
return listFiles(FTPFile.TYPE_FILE);
}
public List<String> listDirectores() {
return listFiles(FTPFile.TYPE_DIRECTORY);
}
private List<String> listFiles(int type) {
mCommandAttempts = 5;
return attemptListFiles(type);
}
private List<String> attemptListFiles(int type) {
ArrayList<String> names = new ArrayList<>();
try {
FTPFile[] files = mFtpClient.list();
for (FTPFile file : files) {
if (file.getType() == type) {
names.add(file.getName());
}
}
} catch (Exception e) {
Log.e(LOG_TAG, e.toString());
try {
TimeUnit.MILLISECONDS.sleep(REPEAT_TIMEOUT_MILLIS);
} catch (InterruptedException e1) {
Log.e(LOG_TAG, e.toString());
return names;
}
mCommandAttempts--;
if (mCommandAttempts > 0) {
return attemptListFiles(type);
}
}
return names;
}
public boolean downloadFile(OutputStream outputStream, String ftpName) {
mCommandAttempts = 5;
return attemptDownloadFile(outputStream, ftpName);
}
private boolean attemptDownloadFile(OutputStream outputStream, String ftpName) {
try {
mFtpClient.download(ftpName, outputStream, 0, null);
return true;
} catch (Exception e) {
Log.e(LOG_TAG, e.toString());
try {
TimeUnit.MILLISECONDS.sleep(REPEAT_TIMEOUT_MILLIS);
} catch (InterruptedException e1) {
Log.e(LOG_TAG, e.toString());
return false;
}
mCommandAttempts--;
if (mCommandAttempts > 0) {
return attemptDownloadFile(outputStream, ftpName);
}
}
return false;
}
public boolean changeDirectory(String path) {
mCommandAttempts = 5;
return attemptChangeDirectory(path);
}
private boolean attemptChangeDirectory(String path) {
try {
mFtpClient.changeDirectory(path);
return true;
} catch (Exception e) {
Log.e(LOG_TAG, e.toString());
try {
TimeUnit.MILLISECONDS.sleep(REPEAT_TIMEOUT_MILLIS);
} catch (InterruptedException e1) {
Log.e(LOG_TAG, e.toString());
return false;
}
mCommandAttempts--;
if (mCommandAttempts > 0) {
return attemptChangeDirectory(path);
}
}
return false;
}
public boolean release() {
if (mFtpClient != null) try {
mFtpClient.logout();
mFtpClient.disconnect(true);
mFtpClient = null;
return true;
} catch (Exception e) {
Log.e(LOG_TAG, e.toString());
return false;
}
return false;
}
}
And
public class FTPDirectory implements Parcelable {
private StringBuilder builder;
public FTPDirectory(String host) {
builder = new StringBuilder(host);
}
protected FTPDirectory(Parcel in) {
builder = new StringBuilder(in.readString());
}
public static final Creator<FTPDirectory> CREATOR = new Creator<FTPDirectory>() {
#Override
public FTPDirectory createFromParcel(Parcel in) {
return new FTPDirectory(in);
}
#Override
public FTPDirectory[] newArray(int size) {
return new FTPDirectory[size];
}
};
public FTPDirectory append(String path) {
builder.append("/").append(path);
return this;
}
public String getPath() {
return builder.toString();
}
public static FTPDirectory getImgDirectory() {
return new FTPDirectory("/img");
}
public static FTPDirectory getAdDirectory() {
return new FTPDirectory("/adv");
}
public static FTPDirectory getMusicDirectory() {
return new FTPDirectory("/music");
}
public static FTPDirectory getChannelDirectory(String channel, int index) {
return getChannelRootDirectory(channel)
.append(Integer.toString(index));
}
public static FTPDirectory getChannelRootDirectory(String channel) {
return getMusicDirectory()
.append(channel);
}
#Override
public String toString() {
return "FTPDirectory{" +
"Path=" + builder.toString() +
'}';
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getPath());
}
}
I think somewhere here there may be a mistake. It turns out that one file reads and the other does not, but the format is the same. Please help to solve the problem.
I´m try to build a application which, by threads, are listening to directory for changes. Everything works fine, but there is a little bug. I´m very new to the whole threads-thing... So, this problem probably based on my ignorance...
The program can se all the changes in the picked directory, BUT, when the threads are running, i cant modify the files inside the directory... Those are locked in the process...
I will be very happy if someone perhaps can give me some tips in how i can solve this.
Thank you in advance
DirWatch
public class DirWatch implements Runnable{
Path dirPath;
private boolean run = true;
private boolean created = false;
private boolean modified = false;
private boolean compressed = false;
private boolean isJSON = false;
/**
*
* #param path
* #throws IOException
*/
public void setWatchPath(String path) throws IOException {
dirPath = Paths.get(path);
try {
Boolean isFolder = (Boolean) Files.getAttribute(dirPath, "basic:isDirectory", new LinkOption[]{NOFOLLOW_LINKS});
if (!isFolder) {
throw new IllegalArgumentException("Path: " + dirPath + " is not a folder");
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("Watching path: " + path);
}
public void setDirPathWatchRun(boolean run){
this.run = run;
}
public boolean isCreated() {
return created;
}
public void setCreated(boolean created) {
this.created = created;
}
public boolean isModified() {
return modified;
}
public void setModified(boolean modified) {
this.modified = modified;
}
public boolean isCompressed() {
return compressed;
}
public void setCompressed(boolean compressed) {
this.compressed = compressed;
}
public boolean isJSON() {
return isJSON;
}
public void setJSON(boolean JSON) {
isJSON = JSON;
}
private void checkFileType(String fileName){
String extension = fileName.substring(fileName.length() - 4);
if(extension.equalsIgnoreCase(FILE_TYPE.TAR.getFileType())){
setCompressed(true);
System.out.println(extension);
}
if(extension.equalsIgnoreCase(".json")){
setJSON(true);
}
}
#Override
public void run() {
FileSystem fs = dirPath.getFileSystem ();
try(WatchService service = fs.newWatchService()) {
dirPath.register(service, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
WatchKey key = null;
while(run) {
key = service.take();
WatchEvent.Kind<?> kind = null;
for(WatchEvent<?> watchEvent : key.pollEvents()) {
kind = watchEvent.kind();
if (OVERFLOW == kind) {
System.out.println("OVERFLOW");
continue;
} else if (ENTRY_CREATE == kind) {
System.out.println("New path created: " + watchEvent.context().toString());
setCreated(true);
checkFileType(watchEvent.context().toString());
} else if (ENTRY_DELETE == kind){
System.out.println("Path deleted: " + watchEvent.context().toString());
setModified(true);
checkFileType(watchEvent.context().toString());
} else if (ENTRY_MODIFY == kind) {
System.out.println("Path modified: " + watchEvent.context().toString());
setModified(true);
checkFileType(watchEvent.context().toString());
}
}
if(!key.reset()) {
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Method Watch in another class
private void watch() throws IOException {
watchJSON = new DirWatch();
watchTAR = new DirWatch();
watchTAR.setWatchPath(serverArgs.getCompressedPath());
watchJSON.setWatchPath(serverArgs.getExtractedPath());
Runnable checkSourceActions = new Runnable() {
#Override
public void run() {
while(true) {
if (watchJSON.isCreated() || (watchJSON.isModified())) {
server();
}
if(watchTAR.isCreated() || (watchTAR.isModified())) {
extractFiles(fileHandler);
createManifest(fileHandler);
server();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread1 = new Thread(watchJSON);
Thread thread3 = new Thread(watchTAR);
Thread thread2 = new Thread(checkSourceActions);
thread1.start();
thread2.start();
thread3.start();
}
When I try to change the file while the program is running
I am pretty new to writing client/server based apps. both server and client classes are kicked off in threads. New to using Object Output/input streams over tcp aswell. Have never had fun with serialization. In my application I am trying to use Object Input/Output Streaming but it looks like opening them is causing my application dies. The funny thing is that if I comment two lines:
outStream = new ObjectOutputStream(socket.getOutputStream());
inStream = new ObjectInputStream(socket.getInputStream());
Connection works nicely and app proceeds to the next panels etc. But I am still not capable of sending any objects throughout the socket. When I literally try to open those streams. It still connects but app get freezed. I 've got two questions:
first: is it better to use serialization
second: if I can use Object streaming, how should I open them? Can I do it inside the server/client thread?
Thanks for Your time
Here is the code of ClientApp:
public void run()
{
while (true)
{
try // odswiezanie co sekunde
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
try // polaczenie
{
if (connecting)
{
socket = new Socket(hostIP, port);
JOptionPane.showMessageDialog(null, "Connection established!");
connected = true;
connecting = false;
frame.settingPanelForClient.bPlayerName.setText("Put the ships on your board!");
outStream = new ObjectOutputStream(socket.getOutputStream());
inStream = new ObjectInputStream(socket.getInputStream());
connectionEstablished(frame);
}
}
catch (UnknownHostException e)
{
JOptionPane.showMessageDialog(frame, "Unknown server!");
connected = false;
}
catch (IOException e)
{
JOptionPane.showMessageDialog(frame,"An Error occured while trying to connect to the server!");
e.getMessage();
e.printStackTrace();
connected = false;
}
catch (IllegalThreadStateException e)
{
e.printStackTrace();
}
try // odbior obiektow
{
if(connected)
{
while(!opponentIsReady){
System.out.println("wszedlem do connected!(klient) ");
System.out.println(opponentIsReady);
if(!opponentIsReady)
{
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
}
if(iAmReady && !opponentIsReady)
{
System.out.println("wszedlem do iAmReady i wysylam wiadomosc o gotowosci do klienta!");
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
outStream.writeObject(iAmReady);
outStream.flush();
}
if(opponentIsReady)
{
sendMap();
proceedToNextPanel(frame);
opponentIsReady = false;
}
}}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
Do you use Serializable interface for the Map object ?
If you still frozen at a step, its maybe because you try to read object (from server or client) and you didn't send it by the other side. While the object is not read it will wait for content.
I dont know how work your server, but you read response twice when oppenentReady is false.
if (inStream.readObject() != null) {
if (inStream.readObject() instanceof Boolean) {
//...
}
}
If this is not the expected behavior, you should store it in local variable.
Once again, this's smt I want to implement(in steps)
1. user choose to open connection(he becomes a server and waits for a client
to connect) - done.
2. second user choose to connect(becomes a client and connects to the
second player(server) - done.
3. Both get message that the connection is established and they are moved
to the next Panel where they do specific operations - done.
4.When anyone of them finishes, I want to tell it to the second guy
(it is represented by a boolean local varable) - here comes the problem.
5. When both have finished, they should be moved to the next Panel where
they play.(before they start playing, Maps that they have set in the previous Panel
should be sent to each other.
Next steps I can handle if Only I knew maybe not how to send those informations
but where to place sending code because it seems to be in the wrong place. Here is the full code of client/server classes:
connecting - is set to true in the other class after pushing the button.
iAmready - is set to true when player finishes setting up the map and should be sent to opponent,
because it triggers a specific operation by setting opponentIsReady to true when obtained.
public class ClientApp implements Runnable
{
public static String hostIP = "127.0.0.1";
public static int port = 1000;
public static boolean connected = false;
public static boolean connecting = false;
public static boolean iAmReady = false;
public static boolean opponentIsReady = false;
public static Socket socket = null;
public static ObjectInputStream inStream;
public static ObjectOutputStream outStream;
public final Frame frame;
public static Map mapToGet;
public static Map mapToSend;
public ClientApp(Frame parent)
{
frame = parent;
mapToGet = new Map();
mapToSend = new Map();
}
#Override
public void run()
{
while (true)
{
try // odswiezanie co sekunde
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
try // polaczenie
{
if (connecting)
{
socket = new Socket(hostIP, port);
JOptionPane.showMessageDialog(null, "Connection established!");
connected = true;
connecting = false;
frame.settingPanelForClient.bPlayerName.setText("Put the ships on your board!");
connectionEstablished(frame);
}
}
catch (UnknownHostException e)
{
JOptionPane.showMessageDialog(frame, "Unknown server!");
connected = false;
}
catch (IOException e)
{
JOptionPane.showMessageDialog(frame,"An Error occured while trying to connect to the server!");
e.getMessage();
e.printStackTrace();
connected = false;
}
catch (IllegalThreadStateException e)
{
e.printStackTrace();
}
try // odbior obiektow
{
if(connected)
{
FileOutputStream out = new FileOutputStream("/tmp/message.ser");
outStream = new ObjectOutputStream(out);
FileInputStream in = new FileInputStream("/tmp/message.ser");
inStream = new ObjectInputStream(in);
while(!opponentIsReady){
System.out.println("wszedlem do connected!(klient) ");
System.out.println(opponentIsReady);
if(!opponentIsReady)
{
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
}
if(iAmReady && !opponentIsReady)
{
System.out.println("wszedlem do iAmReady i wysylam wiadomosc o gotowosci do klienta!");
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
outStream.writeObject(iAmReady);
outStream.flush();
}
if(opponentIsReady && iAmReady)
{
sendMap();
proceedToNextPanel(frame);
opponentIsReady = false;
}
}
inStream.close();
outStream.close();
in.close();
out.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
public static void connectionEstablished(Frame frame)
{
frame.remove(frame.connectPanel);
frame.getContentPane().add(frame.settingPanelForClient);
frame.validate();
frame.repaint();
}
public static void proceedToNextPanel(Frame frame)
{
frame.remove(frame.settingPanelForClient);
frame.getContentPane().add(frame.opponentsMove);
frame.validate();
frame.repaint();
}
public static Map getMap()
{
try
{
if (connected)
if (inStream.readObject() != null && inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
return mapToGet;
}
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
public static void sendMap()
{
if (connected)
if (mapToSend != null)
{
try
{
outStream.writeObject(mapToSend);
outStream.flush();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public class ServerApp implements Runnable
{
public static int port = 1000;
public static boolean connected = false;
public static boolean connecting = false;
public static boolean iAmReady = false;
public static boolean opponentIsReady = false;
public static Socket socket = null;
public static ServerSocket hostServer = null;
public static ObjectInputStream inStream;
public static ObjectOutputStream outStream;
public static Map mapToGet;
public static Map mapToSend;
final Frame frame;
public ServerApp(Frame parent)
{
frame = parent;
mapToGet = new Map();
mapToSend = new Map();
}
#Override
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e) {}
try
{
if (connecting)
{
hostServer = new ServerSocket(port);
socket = hostServer.accept();
connected = true;
connecting = false;
JOptionPane.showMessageDialog(null, "Connection Established!");
frame.settingPanelForServer.bPlayerName.setText("Put the ships on your board!");
connectionEstablished(frame);
}
}
catch (UnknownHostException e)
{
connected = connecting = false;
}
catch (IOException e)
{
connected = connecting = false;
}
try // odbior obiektow
{
if(connected)
{
while(!opponentIsReady){
System.out.println("wszedlem do connected(server)");
System.out.println(opponentIsReady);
if(!opponentIsReady)
{
inStream = new ObjectInputStream(socket.getInputStream());
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
}
if(iAmReady && !opponentIsReady)
{
System.out.println("wszedlem do iAmReady i wysylam wiadomosc o gotowosci do servera!");
outStream = new ObjectOutputStream(socket.getOutputStream());
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
outStream.writeObject(iAmReady);
outStream.flush();
}
if(opponentIsReady && iAmReady)
{
sendMap();
proceedToNextPanel(frame);
opponentIsReady = false;
}
}}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
public static void connectionEstablished(Frame frame)
{
frame.remove(frame.waitPanel);
frame.getContentPane().add(frame.settingPanelForServer);
frame.validate();
frame.repaint();
}
public static void proceedToNextPanel(Frame frame)
{
frame.remove(frame.settingPanelForServer);
frame.getContentPane().add(frame.playPanelForServer);
frame.validate();
frame.repaint();
}
public static Map getMap()
{
try
{
if (connected)
if (inStream.readObject() != null && inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
return mapToGet;
}
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
public static void sendMap()
{
if (connected)
if (mapToSend != null)
{
try
{
outStream.writeObject(mapToSend);
outStream.flush();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
As i said before, you can not use readObject() more than once for the same object.
Example,
Use:
Object objectRead=inStream.readObject();
if (objectRead != null) {
if (objectRead instanceof Boolean) {
opponentIsReady = Boolean.valueOf(objectRead);
System.out.println(opponentIsReady);
} else if (objectRead instanceof Map) {
mapToGet = (Map) objectRead;
}
}
Instead of:
if(inStream.readObject() != null)
{
if(inStream.readObject() instanceof Boolean)
{
opponentIsReady = inStream.readBoolean();
System.out.println(opponentIsReady);
}
else if(inStream.readObject() instanceof Map)
{
mapToGet = (Map) inStream.readObject();
}
}
I think you didn't understand how it works:
When the client/server connection is etablished you can use Threads to read or write objects.
I give you code that you can test to understand how it works:
ServerApp:
public class ServerApp implements Runnable {
public static int port = 1000;
public static boolean opponentIsReady = false;
public static Socket socket = null;
public static ServerSocket hostServer = null;
public static ObjectInputStream inStream;
public static ObjectOutputStream outStream;
public static Map mapToGet;
public static Map mapToSend;
final Frame frame;
private boolean connected = false;
public ServerApp(Frame parent) {
frame = parent;
mapToGet = new Map();
mapToSend = new Map();
}
#Override
public void run() {
// Server initialization side
try {
hostServer = new ServerSocket(port);
JOptionPane.showMessageDialog(frame, "Waiting for opponent to finish");
// Accept will wait until a client try to connect
socket = hostServer.accept();
JOptionPane.showMessageDialog(null, "Connection Established!");
// Init streams when connection is etablished
inStream = new ObjectInputStream(socket.getInputStream());
outStream = new ObjectOutputStream(socket.getOutputStream());
frame.settingPanelForServer.bPlayerName.setText("Put the ships on your board!");
connectionEstablished(frame);
connected = true;
} catch (IOException ex) {
Logger.getLogger(ServerApp.class.getName()).log(
Level.SEVERE, null, ex);
}
int x = 0;
// The loop is made to send/receive all messages
while (connected) {
try {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ServerApp.class.getName()).log(
Level.SEVERE, null, ex);
}
Object o = String.format("I send you a message (%s)", x++);
outStream.writeObject(o);
Object response = inStream.readObject();
System.out.println("Response: " + response);
} catch (IOException ex) {
Logger.getLogger(ServerApp.class.getName()).log(
Level.SEVERE, null, ex);
connected = false;
} catch (ClassNotFoundException ex) {
Logger.getLogger(ServerApp.class.getName()).log(
Level.SEVERE, null, ex);
connected = false;
}
}
System.err.println("Connection closed");
}
public static void connectionEstablished(Frame frame) {
frame.remove(frame.waitPanel);
frame.getContentPane().add(frame.settingPanelForServer);
frame.validate();
frame.repaint();
}
public static void proceedToNextPanel(Frame frame) {
frame.remove(frame.settingPanelForServer);
frame.getContentPane().add(frame.playPanelForServer);
frame.validate();
frame.repaint();
}
public static Map getMap() {
try {
if (inStream.readObject() != null && inStream.readObject() instanceof Map) {
mapToGet = (Map) inStream.readObject();
return mapToGet;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void sendMap() {
if (mapToSend != null) {
try {
outStream.writeObject(mapToSend);
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ClientApp:
public class ClientApp implements Runnable {
public static String hostIP = "127.0.0.1";
public static int port = 1000;
public static boolean connected = false;
public static boolean connecting = true;
public static boolean iAmReady = false;
public static boolean opponentIsReady = false;
public static Socket socket = null;
public static ObjectInputStream inStream;
public static ObjectOutputStream outStream;
public final Frame frame;
public static Map mapToGet;
public static Map mapToSend;
public ClientApp(Frame parent) {
frame = parent;
mapToGet = new Map();
mapToSend = new Map();
}
#Override
public void run() {
try {
// Client initialization side
socket = new Socket(hostIP, port);
// If the socket connection succeed it pass, else execption is thrown
JOptionPane.showMessageDialog(null, "Connection Established!");
// Initialize streams
outStream = new ObjectOutputStream(socket.getOutputStream());
inStream = new ObjectInputStream(socket.getInputStream());
frame.settingPanelForClient.bPlayerName.setText("Put the ships on your board!");
connectionEstablished(frame);
connected=true;
} catch (IOException ex) {
Logger.getLogger(ClientApp.class.getName()).log(
Level.SEVERE, null, ex);
}
// The loop will receive server message and send response
while (connected) {
try {
Object serverMessage = inStream.readObject();
System.out.println("Server sent: " + serverMessage);
Object myResponse = String.format("I received %s", serverMessage);
outStream.writeObject(myResponse);
} catch (IOException ex) {
Logger.getLogger(ClientApp.class.getName()).log(
Level.SEVERE, null, ex);
connected=false;
} catch (ClassNotFoundException ex) {
Logger.getLogger(ClientApp.class.getName()).log(
Level.SEVERE, null, ex);
connected=false;
}
}
System.err.println("Connection closed");
}
public static void connectionEstablished(Frame frame) {
frame.remove(frame.connectPanel);
frame.getContentPane().add(frame.settingPanelForClient);
frame.validate();
frame.repaint();
}
public static void proceedToNextPanel(Frame frame) {
frame.remove(frame.settingPanelForClient);
frame.getContentPane().add(frame.opponentsMove);
frame.validate();
frame.repaint();
}
public static Map getMap() {
try {
if (connected) {
if (inStream.readObject() != null && inStream.readObject() instanceof Map) {
mapToGet = (Map) inStream.readObject();
return mapToGet;
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void sendMap() {
if (connected) {
if (mapToSend != null) {
try {
outStream.writeObject(mapToSend);
outStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
I have a programm which communicates with MPlayer through Input and Outputstream of the Process.
It works quite good, but I can only communicate with the Process in the Main Thread, and not in any other. Is there a posibility to get arround that?
synchronized-Methods or blocks didn't brought a solution
private String getProperty(String property) {
System.out.println("CurThread: " + Thread.currentThread().getName());
String cmd = "";
cmd = String.format("pausing_keep_force get_property %s", property);
mplayerIn.println(cmd);
mplayerIn.flush();
String rightAnswer = String.format("ANS_%s=", property);
String errorAnswer = "ANS_ERROR";
String answer;
String value = "";
try {
while ((answer = mplayerOut.readLine()) != null) {
if (answer.startsWith(rightAnswer)) {
value = answer.substring(rightAnswer.length());
break;
}
if (answer.startsWith(errorAnswer)) {
value = "";
break;
}
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("Property Error:" + property);
}
return value;
}
edit: ProcessCommunicator
public class ProcessCommunicator extends Thread {
private String cmd;
private BufferedReader is;
private PrintStream os;
List<MessageReceivedListener> listeners;
public boolean addListener(MessageReceivedListener listener) {
return listeners.add(listener);
}
public boolean removeListener(MessageReceivedListener listener) {
if (listeners.contains(listener)) {
return listeners.remove(listener);
}
return false;
}
public ProcessCommunicator(String cmd) {
this.cmd = cmd;
listeners = new ArrayList<>();
}
public void write(String cmd) {
System.out.println(cmd);
os.println(cmd);
os.flush();
}
public void fireEvent(String msg) {
for (MessageReceivedListener listener : listeners) {
listener.received(msg);
}
}
Process p;
#Override
public void run() {
try {
p = Runtime.getRuntime().exec(cmd);
is = new BufferedReader(new InputStreamReader(p.getInputStream()));
os = new PrintStream(p.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
String line;
try {
while ((line = is.readLine()) != null) {
System.err.println(line);
fireEvent(line.trim());
}
} catch (IOException e) {
e.printStackTrace();
}
}
boolean waitForProperty;
String propertyResult;
public String readProperty(String property) {
final String rightAnswer = String.format("ANS_%s=", property);
propertyResult = "";
MessageReceivedListener messageListener = new MessageReceivedListener() {
#Override
public void received(String s) {
if (s.startsWith(rightAnswer)) {
waitForProperty = false;
propertyResult = s.substring(rightAnswer.length());
} else if (s.startsWith("ANS_ERROR")) {
waitForProperty = false;
propertyResult = "";
}
}
};
addListener(messageListener);
waitForProperty = true;
write(String.format("pausing_keep_force get_property %s", property));
int i = 5;
while (waitForProperty && i > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(".");
i--;
}
System.out.println("END");
removeListener(messageListener);
return propertyResult;
}
}