Hi Stuart,

It looks as if you have a problem with instance variables (variables in a
class declared outside a method). All logins are going to be using the same
copy of the code, i.e. same variable space etc.  All synchronizing does is
make sure that the threads play nice when modifying the variables.

Your Hashtable "connections" is an instance variable, so there is only one
copy of it for all calls to connections.  When you fill "connections" with
data, another login may fill it again before you get a chance to copy that
data to a new object.

Also, all those instance variables at the top of your thread class
"ToApplet" are all shared by all instances of "ToApplet".  Every thread is
going to see what was stuffed into them by the last thread created.
Generally you should only do that for data that needs to be the same for all
threads and is initialized once and never changed.

In general, if you are storing anything in an instance variable you might
have problems.  Create a class to hold data and use it instead.

As a simple example, instead of :
String myStr = req.getParameter("blaBla");

use:
StorageClass myData = new StorageClass();
myData.myStr = req.getParameter("blaBla");

That way, you are certain to get a clean one-owner copy of myStr for each
thread as long as you are careful to create and fill it in a sync block.

If you need another method to see your object pass it as a parameter.

The same thing will happen in a JSP if you create a class inside <%! %> and
then call that object's methods with variables in the main JSP page.
Although each call to the JSP will create a new class

Hope this helps,

Rick

>
> Hello,
>
> I'm having touble with my HTTP tunnelling servlet and its driving me
crazy.
> The tunnel works fine for a single user. However when another user
connects
> to the tunnel the servlet does not perform how I would expect it to.
>
> The problem is, that when another user sends a message. ALL instances of
the
> variables seem to swap over to the most recent. However the threads still
> all run. So, if mr x and mr y are in a meeting. Mr x joined first, he says
> 'hello'. Hello is sent and recieved once how I would expect it to do it.
> However, now mr y joins and says 'hello'. and he recieves the messages for
> himself AND for mr x.
>
> This is driving me insane and I can't seem to find a way around it, I
don't
> understand why the entire data structure is being overwritten when it is a
> different request for a different user. The sockets are different, yet
when
> i do the test, they aren't! But the server isnt sending the message out on
> the wrong socket. I've tested that. It's somehow the right sockets,
> recieving the right messages, but then sending them to the wrong place.
But
> how can this be? It makes no sense to me.
>
> The code for the tunnel is below.
>
> Stuart Stephen
>
>
> import javax.servlet.*;
> import javax.servlet.http.*;
> import javax.servlet.ServletException.*;
> import javax.servlet.UnavailableException.*;
> import java.lang.Exception.*;
> import java.io.*;
> import java.util.*;
> import java.net.*;
>
> public class TestTunnel extends HttpServlet {
>
>   Hashtable connections = null;
>
>   protected void service(HttpServletRequest req, HttpServletResponse res)
> throws ServletException, IOException  {
>     try {
>       String method = (String)req.getParameter("method").trim();
>
>       if(method!=null && !method.equalsIgnoreCase("")) {
>         if(method.equalsIgnoreCase("connect")) connectUser(req, res,
> (String)req.getParameter("mid").trim(), "",
> (String)req.getParameter("email").trim());
>         else if(method.equalsIgnoreCase("msg"))
> msgServer((String)req.getParameter("mid").trim(), "",
> (String)req.getParameter("email").trim(),
> (String)req.getParameter("msg").trim());
>         else {
>           System.err.println("redirecting user");
>           res.sendRedirect("http://www.disney.com";);
>         }
>       }
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>     }
>   }
>
>   protected synchronized void msgServer(String mid, String uid, String
> email, String msg) {
>     if(connections!=null) {
>       try {
>         System.err.println("msgServer()");
>         Hashtable meet = (Hashtable)connections.get(mid+""+uid+""+email);
>         if(meet!=null) {
>           ((ToServer)meet.get("ToServer")).write(msg);
>         }
>         else System.err.println("msgServer(): meet == null");
>       }
>       catch(Exception e) {
>         e.printStackTrace();
>       }
>     }
>     else System.err.println("msgServer(): No connections to use.");
>   }
>
>   protected void connectUser(HttpServletRequest req, HttpServletResponse
> res, String mid, String uid, String email) {
>     try {
>       System.err.println("CONNECTING "+mid+""+uid+""+email);
>
>       Socket socket = new Socket("127.0.0.1", 3000);
>       ToApplet app = new ToApplet(socket, res, mid, uid, email);
>       ToServer ser = new ToServer(socket, req, mid, uid, email);
>
>       app.start();
>       ser.start();
>
>       Hashtable meet = new Hashtable();
>       meet.put("ToApplet", app);
>       meet.put("ToServer", ser);
>       meet.put("Socket", socket);
>       if(connections==null) connections = new Hashtable();
>       connections.put(mid+""+uid+""+email, meet.clone());
>
>       while(meet!=null && ((ToServer)meet.get("ToServer")).isAlive() &&
> ((ToApplet)meet.get("ToApplet")).isAlive()) {
>         try {
>           System.err.println("Threads alive");
>           Thread.sleep(1000);
>         }
>         catch(Exception ex) {
>           ex.printStackTrace();
>         }
>       }
>
>       if(meet!=null) {
>         try { ((ToServer)meet.get("ToServer")).objIn.close(); }
> catch(Exception ex) { }
>         try { ((ToServer)meet.get("ToServer")).sockObjOut.close(); }
> catch(Exception ex) { }
>         try { ((ToApplet)meet.get("ToApplet")).objOut.close(); }
> catch(Exception ex) { }
>         try { ((ToApplet)meet.get("ToApplet")).sockObjIn.close(); }
> catch(Exception ex) { }
>         try { ((Socket)meet.get("Socket")).close(); } catch(Exception ex)
> { }
>       }
>       else System.err.println("connectUser(): meet == null");
>       connections.remove(mid+""+uid+""+email);
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>     }
>     System.err.println("DISCONNECTED "+mid+""+uid+""+email);
>   }
> }
>
> class ToApplet extends Thread implements Runnable {
>   DataInputStream sockObjIn = null;
>   DataOutputStream objOut = null;
>
>   String mid = null;
>   String uid = null;
>   String email = null;
>   Socket socket = null;
>   HttpServletResponse res = null;
>
>   boolean isAlive = true;
>
>   public ToApplet(Socket socket, HttpServletResponse res, String mid,
String
> uid, String email) {
>     try {
>       this.objOut = new DataOutputStream(res.getOutputStream());
>       this.sockObjIn = new DataInputStream(socket.getInputStream());
>       this.mid = mid;
>       this.uid = uid;
>       this.email = email;
>       this.socket = socket;
>       this.res = res;
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>     }
>   }
>
>   public void run() {
>     try {
>       String obj = null;
>       while((obj = this.sockObjIn.readLine())!=null) {
>         System.err.println("Read a line from "+mid+""+uid+""+email+"
> "+sockObjIn.toString()+" "+socket.toString()+" "+res.toString());  //
> obviously coming from the right socket, but the variables are incorrect.
>         this.write(obj);
>       }
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>     }
>     isAlive = false;
>   }
>
>   public boolean connIsAlive() {
>     return isAlive;
>   }
>
>   public void write(String msg) {
>     try {
>       System.err.println("S-->A "+mid+""+uid+""+email+" "+msg);
>       objOut.writeUTF(msg+"\r\n");
>       objOut.flush();
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>       isAlive = false;
>     }
>   }
> }
>
> class ToServer extends Thread implements Runnable {
>   DataInputStream objIn = null;
>   DataOutputStream sockObjOut = null;
>
>   String mid = null;
>   String uid = null;
>   String email = null;
>
>   boolean isAlive = true;
>
>   public ToServer(Socket socket, HttpServletRequest req, String mid,
String
> uid, String email) {
>     try {
>       this.sockObjOut = new DataOutputStream(socket.getOutputStream());
>       this.objIn = new DataInputStream(req.getInputStream());
>       this.mid = mid;
>       this.uid = uid;
>       this.email = email;
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>     }
>   }
>
>   public void run() {
>     try {
>       while(isAlive) {
>         Thread.sleep(1000);
>       }
>     }
>     catch(Exception e) {
>     }
>     System.err.println("ToServer() thread finished.");
>   }
>
>   public boolean connIsAlive() {
>     return isAlive;
>   }
>
>   public void write(String msg) {
>     try {
>       System.err.println("S<--A "+mid+""+uid+""+email+" "+msg);
>       sockObjOut.writeUTF(msg+"\r\n");
>       sockObjOut.flush();
>     }
>     catch(Exception e) {
>       e.printStackTrace();
>       isAlive = false;
>     }
>   }
> }
>
>
>
> --
> To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
>
>
>
> --
> To unsubscribe, e-mail:
<mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail:
<mailto:[EMAIL PROTECTED]>
>
>


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to