Migrating application made with Processing.org to Eclipse - java
I made a simple program in Processing, and it works great. Im now attempting to bring my beginner Java skills to Eclipse to make the same program over again. The program takes a Rs232 string that comes from the Com port and sends it over Xmpp.
The issue I'm having is that i cant call newChat.sendMessage(message) like i can in processing from any of the Classes/Tabs. Can someone clue me in to what i should look for to fix this issue. I'm guessing Extending, or implementing the Xmpp class is what i need to do. I love how simple processing handles it..
Any help will be greatly appreciated.
Fyi: the Smack library's are in the code folder for processing.
Main Application:
import processing.net.*;
void setup() {
size(400, 200);
noStroke();
background(0);
LoadSerialPort();
OpenChatConnection();
setupFilterThread ();
}
void draw() {
}
String timestampTime() {
Calendar now = Calendar.getInstance();
return String.format("%1$tH:%1$tM:%1$tS", now);
}
String timestampDate() {
Calendar now = Calendar.getInstance();
return String.format("%1$tm/%1$td/%1$tY", now);
}
Filter Class/Tab:
FilterThread thread1;
List FilteredArchAddressList = new ArrayList();
ArrayList CallList = new ArrayList();
void setupFilterThread () {
thread1 = new FilterThread(100, "a");
thread1.start();
}
void checkForNewCalls() {
if (CallList.size() >=1) {
println("New Call In List, Size: "+CallList.size());
FilterComPortString((String) CallList.get(0));
CallList.remove(0);
}
}
void FilterComPortString(String s) {
Message message = new Message("icu1#broadcast.server", Message.Type.normal);
//message.setTo("icu1#broadcast.x-dev");
message.setSubject("MSG_TYPE_NORMAL");
message.setBody(s);
message.setProperty("systemID", "JS1");
message.setProperty("serverTime", trim(timestampTime()));
message.setProperty("serverDate", trim(timestampDate()));
try {
newChat.sendMessage(message);
}
catch (Exception e) {
println(e);
}
}
}
class FilterThread extends Thread {
boolean running; // Is the thread running? Yes or no?
int wait; // How many milliseconds should we wait in between executions?
String id; // Thread name
int count; // counter
// Constructor, create the thread
// It is not running by default
FilterThread (int w, String s) {
wait = w;
running = false ;
id = s;
count = 0;
}
int getCount() {
return count;
}
// Overriding "start()"
void start () {
// Set running equal to true
running = true ;
// Print messages
println ("Starting thread (will execute every " + wait + " milliseconds.)");
// Do whatever start does in Thread, don't forget this!
super .start();
}
// We must implement run, this gets triggered by start()
void run () {
while (running) {
checkForNewCalls();
// Ok, let's wait for however long we should wait
try {
sleep((long )(wait));
}
catch (Exception e) {
}
}
System.out.println (id + " thread is done!"); // The thread is done when we get to the end of run()
}
// Our method that quits the thread
void quit() {
System.out.println ("Quitting.");
running = false ; // Setting running to false ends the loop in run()
// IUn case the thread is waiting. . .
interrupt();
}
}
Rs232 Class/Tab:
import processing.serial.*;
Serial myPort; // Rs232, Serial Port
String inString; // Input string from serial port:
int lf = 10; // ASCII linefeed
String SelectedCom;
void LoadSerialPort() {
println(Serial.list());
println("________________________________________________________");
try {
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil(lf);
SelectedCom = Serial.list()[0];
println("Connected to Serial Port:");
println("________________________________________________________");
}
catch (ArrayIndexOutOfBoundsException e) {
String exception = e.toString();
if (exception.contains("ArrayIndexOutOfBoundsException: 0")) {
println("NO AVAILABLE COM PORT FOUND");
}
else {
println(e);
}
}
}
void serialEvent(Serial p) {
inString = p.readString();
CallList.add(new String(inString));
}
Xmpp Class/Tab:
String FromXmpp = "";
Chat newChat;
ChatManager chatmanager;
XMPPConnection connection;
public void OpenChatConnection() {
// This is the connection to google talk. If you use jabber, put other stuff in here.
ConnectionConfiguration config = new ConnectionConfiguration("192.168.0.103", 5222, "Jabber/XMPP");
config.setSASLAuthenticationEnabled(false);
configure(ProviderManager.getInstance());
connection = new XMPPConnection(config);
println("Connecting");
try {
//connection.DEBUG_ENABLED = true;
connection.connect();
println("Connected to: "+connection.getServiceName() );
}
catch (XMPPException e1) {
println("NOT Connected");
}
if (connection.isConnected()) {
try {
// This is the username and password of the chat client that is to run within Processing.
println("Connecting");
connection.login("System1", "test");
//connection.login("inside_processing_username#gmail.com", "yourpassword");
}
catch (XMPPException e1) {
// would probably be a good idea to put some user friendly action here.
e1.printStackTrace();
}
println("Logged in as: "+connection.getUser() );
}
chatmanager = connection.getChatManager();
// Eventhandler, to catch incoming chat events
newChat = chatmanager.createChat("icu#broadcast.server", new MessageListener() { //icu1#broadcast.x-dev //admin#x-dev
public void processMessage(Chat chat, Message message) {
// Here you do what you do with the message
FromXmpp = message.getBody();
// Process commands
//println(FromXmpp);
}
}
);
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries) {
System.out.println(entry);
}
}
public void configure(ProviderManager pm) {
// Private Data Storage
pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());
// Time
try {
pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
}
catch (ClassNotFoundException e) {
println(("TestClient "+" Can't load class for org.jivesoftware.smackx.packet.Time"));
}
// Roster Exchange
pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider());
// Message Events
pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider());
// Chat State
pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
// XHTML
pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());
// Group Chat Invitations
pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider());
// Service Discovery # Items
pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
// Service Discovery # Info
pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
// Data Forms
pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
// MUC User
pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider());
// MUC Admin
pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider());
// MUC Owner
pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());
// Delayed Delivery
pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider());
// Version
try {
pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
}
catch (ClassNotFoundException e) {
// Not sure what's happening here.
}
// VCard
pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
// Offline Message Requests
pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());
// Offline Message Indicator
pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());
// Last Activity
pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
// User Search
pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
// SharedGroupsInfo
pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider());
// JEP-33: Extended Stanza Addressing
pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider());
// FileTransfer
pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider());
pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
// Privacy
pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());
pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.MalformedActionError());
pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadLocaleError());
pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadPayloadError());
pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadSessionIDError());
pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.SessionExpiredError());
}
If you know your way around eclipse, first you need to create a new Java project and add Processing's core.jar to the build path and start by creating a sublcass of PApplet. If not, there's a really easy to work with eclipse plugin called Proclipsing and video guide to get started with it.
Bringing your code from Processing to eclipse:
You need to understand that all the code you have in a Processing sketch (including tabs) gets merged into a single .java file and the sketch name is the class name. Any classes you define in tabs in the sketch become nested classes in a main single class. Easiest way to see this is to export an applet and have a look in the generated folder for the SketchName.java file. Remember, a tab is not a class (although it can contain one).
So you've got a few options. Here are two basic approaches:
Create a new PApplet subclass and start pasting your whole code in it (including content of tabs). You will need to de explicit about accessors (e.g. public void setup() instead of just void setup()) and be careful with double/float values (e.g. if eclipse complains about 1.0, be explicit: 1.0f)
The other option is to create multiple classes, as I imagine you intend to do if you're using eclipse. The catch is, in Processing, variables defined in tabs are actually 'global' variables. Your code would work the same way if you declare those in the main tab at the top. Also, using PApplet functions needs to be refactored. Some functions can be called using Java's classes (not PApplet's) to break the dependency: e.g. System.out.println() instead of println(), but of others you might want your classes to have access to a PApplet instance:
e.g.
public class FilterThread extends Thread {
boolean running; // Is the thread running? Yes or no?
int wait; // How many milliseconds should we wait in between executions?
String id; // Thread name
int count; // counter
YourSketchClass parent;
// Constructor, create the thread
// It is not running by default
FilterThread (int w, String s,YourSketchClass p) {
wait = w;
running = false ;
id = s;
count = 0;
parent = p;
}
int getCount() {
return count;
}
// Overriding "start()"
public void start () {
// Set running equal to true
running = true ;
// Print messages
System.out.println ("Starting thread (will execute every " + wait + " milliseconds.)");
// Do whatever start does in Thread, don't forget this!
super .start();
}
// We must implement run, this gets triggered by start()
public void run () {
while (running) {
parent.checkForNewCalls();
// Ok, let's wait for however long we should wait
try {
sleep((long )(wait));
}
catch (Exception e) {
}
}
System.out.println (id + " thread is done!"); // The thread is done when we get to the end of run()
}
// Our method that quits the thread
void quit() {
System.out.println ("Quitting.");
running = false ; // Setting running to false ends the loop in run()
// IUn case the thread is waiting. . .
interrupt();
}
}
Every class which uses the chat-functionality, needs to know the chat-object. You can put all your variables and functions which are not in a separate class in the main source-file.
When you declare a variable in Processing, it can be used from any tab, in java global variables do not exist. You can get a similar functionality like this: Create a new file GlobalVars.java with this content:
public class GlobalVars {
public static Chat myChat;
}
Now everytime you want to access the Chat-functions, you have to write e.g. GlobalVars.myChat.sendMessage("Hi!");
Btw, You have to include the net.jar-file. On Mac this is located here:
Processing.app/Contents/Resources/Java/modes/java/libraries/net/library/net.jar
Related
Stellar Payment code not working in Java
I have referred documentation on Stellar. Then I have started to run the send payment and receiving payment code after creating an account in Java. Send payment code is working , but receiving payment code got terminated. I have mentioned code below : public class receivePayment { public static void main(String args[]) { Server server = new Server("https://horizon-testnet.stellar.org"); KeyPair account = KeyPair.fromAccountId("GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF"); // Create an API call to query payments involving the account. PaymentsRequestBuilder paymentsRequest = server.payments().forAccount(account); // If some payments have already been handled, start the results from // the // last seen payment. (See below in `handlePayment` where it gets // saved.) /* * String lastToken = loadLastPagingToken(); if (lastToken != null) { * paymentsRequest.cursor(lastToken); } */ // `stream` will send each recorded payment, one by one, then keep the // connection open and continue to send you new payments as they occur. paymentsRequest.stream(new EventListener<OperationResponse>() { #Override public void onEvent(OperationResponse payment) { // Record the paging token so we can start from here next time. // savePagingToken(payment.getPagingToken()); // The payments stream includes both sent and received payments. // We only // want to process received payments here. if (payment instanceof PaymentOperationResponse) { if (((PaymentOperationResponse) payment).getTo().equals(account)) { return; } String amount = ((PaymentOperationResponse) payment).getAmount(); Asset asset = ((PaymentOperationResponse) payment).getAsset(); String assetName; if (asset.equals(new AssetTypeNative())) { assetName = "lumens"; } else { StringBuilder assetNameBuilder = new StringBuilder(); assetNameBuilder.append(((AssetTypeCreditAlphaNum) asset).getCode()); assetNameBuilder.append(":"); assetNameBuilder.append(((AssetTypeCreditAlphaNum) asset).getIssuer().getAccountId()); assetName = assetNameBuilder.toString(); } StringBuilder output = new StringBuilder(); output.append(amount); output.append(" "); output.append(assetName); output.append(" from "); output.append(((PaymentOperationResponse) payment).getFrom().getAccountId()); System.out.println(output.toString()); } } }); } } I don't understand why it gets terminated. If I checked the balance from my account URL, but shows me the sending-receiving result, but it is not showing result in Eclipse. I have also referred below reference link and follow the answer but still it is not working. Stellar payments query Can anyone tell me how to run this code which continuously receive the payments and maintain the logs on console. ?
The thing is this is a streaming service, so if you just run the service in main method then it will obviously terminated while running in main method and the scope will go outside and EventListener will not be able to be executed. As you said you are using eclips,one thing you can do is instead of run try debug and insert a debugpoint at this Server server = new Server("https://horizon-testnet.stellar.org"); line and press F6 and go one by one line. While debugging Once it reaches the last line of the program then wait,don't run. You will see the data in the console. this way you will understand how the program is working. If you want to run it fast then use the code that I have added with the existing code. I have added two options. you can use any of this. This will display the output. public class TestStellar2 { public static void main(String args[]) { Server server = new Server("https://horizon-testnet.stellar.org"); KeyPair account = KeyPair.fromAccountId("GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF"); PaymentsRequestBuilder paymentsRequest = server.payments().forAccount(account); paymentsRequest.stream(new EventListener <OperationResponse>(){ #Override public void onEvent(OperationResponse payment) { if (payment instanceof PaymentOperationResponse) { if (((PaymentOperationResponse) payment).getTo().equals(account)) { return; } String amount = ((PaymentOperationResponse) payment).getAmount(); Asset asset = ((PaymentOperationResponse) payment).getAsset(); String assetName; if (asset.equals(new AssetTypeNative())) { assetName = "lumens"; } else { StringBuilder assetNameBuilder = new StringBuilder(); assetNameBuilder.append(((AssetTypeCreditAlphaNum) asset).getCode()); assetNameBuilder.append(":"); assetNameBuilder.append(((AssetTypeCreditAlphaNum) asset).getIssuer().getAccountId()); assetName = assetNameBuilder.toString(); } StringBuilder output = new StringBuilder(); output.append(amount); output.append(" "); output.append(assetName); output.append(" from "); output.append(((PaymentOperationResponse) payment).getFrom().getAccountId()); System.out.println(output.toString()); } } }); /** * option 1 * */ /*try { System.in.read(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ /** * option 2 */ try { Thread.currentThread().join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } The output will look like below : 10.0000000 lumens from GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF many line like this
Why is my boolean not being changed?
So I'm trying to create a client/server program. I want to know when my client disconnects of his own accord, so I've setup a heartbeat system. Every 6 seconds my client sends a ping to my server, if the client doesn't send a ping for a total of 30 seconds the client is considered disconnected and removed from the current connections list (for which I plan to implement a GUI). Or at least, that's the plan. ConnectionManager.java public class ConnectionManager implements Runnable{ static Socket connection; private ArrayList<Thread> allConnections; private ArrayList<Connection> allConnectionList; private ServerSocket server; private int id = 0; public ConnectionManager() { allConnections = new ArrayList<Thread>(); allConnectionList = new ArrayList<Connection>(); } #Override public void run() { try { server = new ServerSocket(5555); System.out.println("Server is running!"); while(true) { connection = server.accept(); Connection a = new Connection(connection, id); Runnable runnable = a; allConnectionList.add(a); allConnections.add(new Thread(runnable)); allConnections.get(allConnections.size() - 1).start(); id++; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void removeConnection(int id) { allConnections.remove(id); allConnectionList.remove(id); } Connection.java public class Connection implements Runnable { private Socket a; public boolean amIActive; private int id; public Connection(Socket a, int id) { amIActive = true; this.a = a; this.id = id; } public void onConnect() { try { String TimeStamp = new java.util.Date().toString(); String formattedAddress = a.getInetAddress().toString().replace("/", ""); System.out.println("Received connection from: " + formattedAddress + " at " + TimeStamp); Runnable runnable = new ConnectionListener(this); Thread connectionThread = new Thread(runnable); connectionThread.start(); String returnCode = "Server repsonded to " + a.getInetAddress().toString().replace("/", "") + " at "+ TimeStamp + (char) 13; BufferedOutputStream os = new BufferedOutputStream(a.getOutputStream()); OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII"); osw.write(returnCode); osw.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } #Override public void run() { onConnect(); System.out.println("We got this far!"); while(amIActive) { whileTrue(); } System.out.println("This code never gets run because we get stuck in the while loop above"); Main.b.removeConnection(id); System.out.println("Connection was closed from " + a.getInetAddress()); } public void setOffline(boolean state) { this.amIActive = state; } public void whileTrue() { } public Socket getSocket() { return a; } ConnectionListener.java public class ConnectionListener implements Runnable{ public Connection myConnection; public boolean receivedHeartbeat; public int missedHeartbeats = 0; public ConnectionListener(Connection a) { this.myConnection = a; } #Override public void run() { Runnable runnable = new Heartbeat(this); Thread thread = new Thread(runnable); thread.start(); while(myConnection.amIActive) { try { BufferedInputStream is; is = new BufferedInputStream(myConnection.getSocket().getInputStream()); InputStreamReader isr = new InputStreamReader(is); StringBuffer process = new StringBuffer(); int character; while((character = isr.read()) != 13) { //GETTING STUCK HERE BECAUSE STUPID. if(character == -1) { myConnection.setOffline(true); } else { process.append((char)character); } } handleInput(process); } catch (Exception e) { e.printStackTrace(); } } } public void handleInput(StringBuffer process) { String messageSent = process.toString(); if(messageSent.equals("Ping!")) { receivedHeartbeat = true; } } Heartbeat.java public class Heartbeat implements Runnable{ private ConnectionListener b; public Heartbeat(ConnectionListener a) { b = a; } #Override public void run() { while(true) { try { Thread.sleep(1000); if(b.missedHeartbeats > 5) { b.myConnection.amIActive = false; System.out.println("Setting amIActiveToFalse!"); } if(b.receivedHeartbeat) { b.receivedHeartbeat = false; } else { b.missedHeartbeats++; } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } My console is spammed with System.out.println("Setting amIActiveToFalse!"); from Heartbeat.java. But the while loop in Connection.java keeps running. I believe this might be something to do with my threading, but I can't figure it out.
When you have a non-volatile variable, there is no guarentee of visability of a change in one thread to another. In particular, if the JVM detects that a thread doesn't alter a boolean it can inline it, meaning you will never see the value change. The simple solution is to make the boolean volatile and it will not be inlined and one thread will see when another changes it. For more details http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html
The trivial answer to this is: make the variable volatile. Without this, it is allowed for the thread changing the value to basically keep its updates in cache, committing them to main memory some time later. This allows threaded code to run much faster, since it can keep its variables in cache rather than having to fetch from main memory. However, the consequence of this is that other threads don't see the update. Making the variable volatile prevents this from happening: a thread always reads the value from main memory, and writes are immediately committed. I say that this is the trivial answer because it doesn't necessarily fix all of your problems. There may also be an atomicity issue: in between one thread reading the variable and writing it again, another thread might sneak in and change its value, which may or may not put the first thread into an undefined state from the perspective of its invariants. Specifically: if(b.receivedHeartbeat) { b.receivedHeartbeat = false; It is possible that some other thread can change b.receivedHeartbeat to false after this thread evaluates it to true, so this iteration is erroneously counted as a "non-missed" heartbeat. This can be fixed by making the variable a (non-volatile) AtomicBoolean, on which there is an atomic compare-and-set method, which avoids such race conditions. Java Concurrency In Practice is a great reference on these issues, I wholeheartedly recommend it. Look for the topics "visibility" and "atomicity". Also read the advanced chapter on the Java Memory Model. That made me doubt myself at first, but made me a much stronger programmer after I digested it.
There are a couple issues I saw while debugging the code you posted, but I was able to successfully get the heartbeat functionality working. In the Connection Listener class I don't think the if statement with .equals("Ping!") will match, because of the newline character at the end of each line. In the Connection Listener class I would probably put the socket's Input Stream at the top of the loop not inside the loop. (I don't think this will break it but it's probably nicer this way) ConnectionListener Updates: public void run() { Runnable runnable = new Heartbeat(this); Thread thread = new Thread(runnable); thread.start(); BufferedReader br = null; try { //is = new BufferedInputStream(myConnection.getSocket().getInputStream()); br = new BufferedReader(new InputStreamReader(myConnection.getSocket().getInputStream())); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } while(myConnection.amIActive) { try { String processLine = br.readLine(); System.out.println("handleInput:" + processLine); handleInput(processLine); } catch (Exception e) { System.out.println("Exception!"); e.printStackTrace(); } } } public void handleInput(String messageSent) { if(messageSent.startsWith("Ping!")) { //Need to use startsWith, or add newline character receivedHeartbeat = true; System.out.println("receivedHeartbeat!"); } } Also, in your Heartbeat class make sure you reset the missedHeartbeats counter to 0 on true: if(b.receivedHeartbeat) { b.receivedHeartbeat = false; b.missedHeartbeats = 0; } else { b.missedHeartbeats++; }
Capture ping packets throws exception (too many instances)
I have written a code snippet to cpature ping using JPCAP. the code I have written is given below : while (true) { try { PacketCapture m_pcap; m_pcap = new PacketCapture(); m_pcap.open("\\Device\\NPF_{007262BD-....-7EE83D72EBEA}",true);//param 1 is actual device ID m_pcap.setFilter("proto ICMP", true); pktlistener a = new pktlistener(); //handles the packet m_pcap.addPacketListener(a); System.out.println("going to sleep"); Thread.sleep(1 * 1000);// Waiting for 1 second before ending capture System.out.println("woken up"); m_pcap.removePacketListener(a); m_pcap.endCapture(); m_pcap.close(); a = null; m_pcap = null; } catch (Exception e) { e.printStackTrace(); } } Now the above code starts a new capture after every one second. The problem with the above is that after 10 runs of the loop, it throws the exception : Exception in thread "Thread-6" java.lang.Error: Too many instances, exceeds 10 at net.sourceforge.jpcap.capture.PacketCapture.<init>(PacketCapture.java:51) Q1. How do i prevent this. I need to start a new PacketCapture every second. Q2. Is there any other simpler way to capture ping messages recived on a system through java?
You cannot use the constructor of PacketCapture more than ten times. This behavior is hardcoded as the constructor looks like this: /** * Create a new packet capture instance. */ public PacketCapture() { if (nextInstance >= INSTANCE_MAX) { throw new Error("Too many instances, exceeds " + INSTANCE_MAX); } instanceNum = nextInstance++; } To capture ping requests, you should try the following code public class Main { public static void main(String[] args) throws CaptureDeviceLookupException { Capture cap = new Capture(); cap.doCapture(); } } class PingListener implements PacketListener { #Override public void packetArrived(Packet packet) { try { // only ICMP packages if (packet instanceof ICMPPacket) { ICMPPacket tcpPacket = (ICMPPacket) packet; int data = tcpPacket.getMessageCode(); // only echo request packages if (data == ICMPMessages.ECHO) { // print source and destination. String srcHost = tcpPacket.getSourceAddress(); String dstHost = tcpPacket.getDestinationAddress(); System.out.println("Ping from: " + srcHost + " to " + dstHost); } } } catch (Exception e) { e.printStackTrace(); } } } class Capture { public void doCapture() { // create capture instance PacketCapture capture = new PacketCapture(); // add listener that handles incomming and outgoing packages PingListener pingListener = new PingListener(); capture.addPacketListener(pingListener); // m_pcap.setFilter("filter here or in handler", true); try { capture.open("\\Device\\NPF_{...}", true); // connect capture to device while (true) { capture.capture(1); // capture one package } } catch (Exception e) { e.printStackTrace(); // exception during capture or handling of // packages } finally { // technically never reached as the loop goes on forever. // if loop terminates after a while then: // remove listener capture.removePacketListener(pingListener); // end capture (only necessary, if PacketCapture still waits for // other packages) capture.endCapture(); // close connection to capture device capture.close(); } } } I think there is a misunderstanding of the class PacketCapture. It does not actually capture one package and is then discarded. It opens a connection to the device you want to capture packages of and then starts listening for as long as you hold that connection. You then start capturing n packages by calling capture.capture(n). For each package arriving while "capture" blocks your program, the listener is called. Alternatively you can drop the while-loop and use capture.capture(-1). This will block your program forever until you close the capture from another device.
Issue initializing jFrame
I'm creating a client window that retrieves from a javaSpace, this is the code I'm using. /** * Create the frame. */ public Client() { space = SpaceUtils.getSpace(); if (space == null) { System.err.println("Failed to find the javaspace"); System.exit(1); } initFrame(); setVisible(true); processPrintJobs(); } The window is generated inside of initFrame(); and then processPrintJobs checks to see if there are any new messages. If I comment out the processPrintJobs() method call then the window draws correctly but if the method call is there, the window just shows a blank square. Its like the window is not being created correctly due to the process being checked lots of times, which makes no sense as the window is created before the while loop is run. public void processPrintJobs() { while (true) { try { Message template = new Message(); if (channel == null) { System.out.println("No channel given"); } else { template.Channel = channel; // System.out.println(channel); template.position = new Integer(getNumber() + 1); Message msg = (Message) space.read(template, null, Long.MAX_VALUE); messageList.append(msg.execute()); } } catch (Exception e) { e.printStackTrace(); } } }
This infinite while loop will block the EDT. while (true) Simply calling setVisible(true); does not guarantee that the JFrame will be painted immediately. Any long-lived processes should be handled by a SwingWorker.
Use java.awt.EventQueue.invokeLater(new Runnable() { #Override public void run() { processPrintJobs(); } } But in general, the architecture of your application is missing some aspects. Like a thread or whatever. More: You could for instance use a swing Timer, for one single job every tick. import javax.swing.Timer; To be called at the end of the Client constructor. Timer printJobsTimer = new Timer(100, new ActionListener() { public void actionPerformed(ActionEvent e) { // Process a print job: if (channel != null) { Message template = new Message(); template.Channel = channel; template.position = new Integer(getNumber() + 1); Message msg = (Message) space.read(template, null, Long.MAX_VALUE); messageList.append(msg.execute()); } } }); printJobsTimer.setInitialDelay(100); printJobsTimer.start(); For the rest, consisting naming would have been fine: just class names starting with a capital and other names with a small letter.
LinkedList queue implementation
I have LinkedList Queue, and I'm trying to read a file with numbers of people in queue waiting to be helped and the number of agents available to help at the time. I do not know to check if they are busy or how to add the people waiting in the queue in the first place. Can anyone help me? This is the code I have so far. public class WaitingQueue { public int [] windows = 0; // every time we add some one check if location occupied public int time = 0; public int waitTime = 0; public static void main(String args[]) { Queue newQueue = new Queue(); try{ FileInputStream fn = new FileInputStream(args[0]); BufferedReader br = new BufferedReader(new InputStreamReader(fn)); String line; while((line = br.readLine()) != null) { time++; // happens every time window i busy waitTime++ // increment waiTime if ( time for people to arrive) { add people to the queue // have to have a queue for people waiting. //use enque to add people. } if(window is open) { // move people from queue to window // use dequeue } if(time = x;) { // add some people to list } } //Close the input stream outFile.close(); fn.close(); } }catch (Exception e) {/*Catches exception*/ System.err.println("An error has occured : " + e.getMessage()); } }
--EDIT-- I see your code has now been tagged in Java; my code is more of a c#/pseudo, so you might need to convert it into Java. --EDIT-- Though this may not help. But I'd suggest a more entity orient approach; something like: Agents, Agent List: Shall list the available agents Customers, Customer Queue: Shall maintain a queue of customers wanting help CustomerSupport Manager: Shall see if an agent is available(not busy) Dequeue the customer Assign it to one of the available agents Above the top of my head, see following: Customer: public class Customer { string _strName; public Customer(string strName) { _strName = strName; } } Agent: public class Agent { string _strName; bool _bIsBusy = false;// public bool IsBusy { get { return _bIsBusy; } } Customer _Customer; public Agent(string strName) { _strName = strName; } public void HandleCustomer(Customer theCustomer) { _Customer = theCustomer; _bIsBusy = true;//Busy as long as the window is open. //You might need something that doesnt block; Thread.Sleep(5 * 1000); //Wait for time to simulate that agent is talking to customer RemoveCustomer();//Done with the customer. } private void RemoveCustomer() { _Customer = null; _bIsBusy = false; } } Manager: A class that manages the customers and agents, according to availability public class CustomerServiceBench { Queue<Customer> queCustomers = new Queue<Customer>(); List<Agent> lstAgents = new List<Agent>(); Thread thdService; public CustomerServiceBench() { //Something along these lines. thdService = new Thread(delegate() { WaitAndAddCustomerIfAgentIsAvailable(); }); } private void AddCustomer() { //Add a dummy customer. Random r = new Random(1231); queCustomers.Enqueue(new Customer("Customer" + r.Next().ToString())); Thread.Sleep(5 * 1000); //SpinWait.Once()... } private void WaitAndAddCustomerIfAgentIsAvailable() { //Thread1 to manage the } }
It's not trivial so I suggest you search a bit for a tutorial with lots of example code and then alter it to suit your needs. 8.3 The Producer/Consumer Pattern - Java Threads, Third Edition The producer-consumer pattern in Java 5: using blocking queues in preference to wait()/notify()