3

I've been thinking about this all day, i dont really think if the Title is the correct one but here it goes, let me explain my situation: Im working on a project, a server made in Java for clients made in Delphi. Conections are good, multiple clients with its own threads, i/o working good. The clients send Strings to the server which i read with BufferedReader. Depending on the reserved words the server receives, it makes an action. Before the client sends the string, it inserts information to a SQL Server database so the server can go and check it after getting the order/command via socket. The server obtains the information in the database, process it, and send it to... let's call it "The Dark Side".

At the moment that the transaction is done, and the info is sent to the dark side, the server inserts the information... cough cough, dark information into a database table so the client can go and take what it requested. BUT, i need to report that to the client! ("Yo, check again the database bro, what you want is there :3").

The conection, the socket is made in other class. Not the one that i want to use to answer to the client, so if i dont have the socket, i dont have the OutputStream, which i need to talk back. That class, the one processing and sending information to the dark side, is going to be working with hundred of transactions in group.

My Issue is here: I can't report to the client that is done because i dont have the sockets references in that class. I instance the clients thread like:

new Client(socket).start(); 

Objects without references variables, but, i have an option i can take: Store the Sockets and their ip's in a HashMap object at the moment that a new connection is made, like this:

sockets.put(newSocket.getInetAddress().getHostAddress(), newSocket);

Then i can get the socket(so i can get the OutputStream and answer) calling an static method like this:

 public static Socket getSocket(String IP) {

        Socket RequestedSocket;
        RequestedSocket = sockets.get(IP);

        return RequestedSocket;
    }

But i want you to tell me if there is a better way of doing this, better than storing all of those sockets in a list/hashmap. How can i get those objects without reference variables ? Or maybe thats a good way of doing it and im just trying to overpass the limits.

P.S.: I tried to store the Client objects in the database, serializing them, but the sockets can't be serialized.

Thanks.

user2245180
  • 161
  • 6
  • what holds you from keeping a reference in the `Client` class ? – A4L May 02 '13 at 18:51
  • There is a reference in the client class, (new Client()) , but i dont have all the references for the Client classes. Thanks for answering – user2245180 May 02 '13 at 19:00
  • 1
    I would suggest you keep track of your clients in some way, not the sockets, and then add a method to the `Client` class to notify the clients, something like `Client#notify("data is available")` – A4L May 02 '13 at 19:08
  • you say you do not have control over the client code but you want suggestions on how to change the process so they can know that their job is done and they can grab the results. how are you going to be able to make changes in the server work if the clients do not change their code? – tgkprog May 03 '13 at 08:31
  • What i exactly want is a way to advice them that their job is done, via Socket, i mean, just the message. With hashmap i can do it, but i just wanted to see if people have a better way of doing it. But i would close the conections and set that position in the hashmap to Null, so the garbage colector do the other job – user2245180 May 03 '13 at 12:33
  • The client code would stay the same, because at the end all he want is the message, via socket – user2245180 May 03 '13 at 12:37

3 Answers3

0

This is a design issue for you. You will need to keep track of them somewhere, one solution might be to simply create a singleton class [SocketMapManager] for instance that holds the hashmap, so that you can access it statically from other classes. http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html

Jack Straw
  • 586
  • 4
  • 10
  • what do you think will happen to those socket connections if they are held open for an indeterminate time? do you think singleton is a place to hold connections or a con pool? do you have experience in this (sockets and open streams)? – tgkprog May 03 '13 at 09:52
0

Any solution that tells you to keep a reference to the socket/ connection/ stream is bad -> as that means your connections are going to be held up while the server does its work.

You have a couple of options open 1. have the clients act as servers too. when they connect, they give the server their IP, port and some secret string as part of the hand shake. This means you have control over client code to make this happen.

  1. the servers have a protocol to either take new jobs or check status of old jobs. Client pools the server periodically.

  2. clients connect to database or other application (web service or plain socket like the original app) that connects to data base to get the status of the job. Meaning server gives client a job id.

a socket is open then it one OS resource open. can read up Network Programming: to maintain sockets or not?

All depends on 1. how many client connect at a time/ in 5 minutes. 2. how many seconds/ minutes does one client's request take to process

if number of clients in 5 minutes is maximum (in next 3 years) 300 at a time/ in any 5 minute duration and each request takes at a max 50 seconds to process then a dedicated server with max 50,000 sockets should suffice. Else you need async or more servers (and a DNS/ web server/ port forwarding or other method for load balance)

Community
  • 1
  • 1
tgkprog
  • 4,493
  • 4
  • 41
  • 70
  • Thanks for answering. I liked that way of doing it, it would be really good like that, the client going by itselft, cheking if the transaction is done, storing an id or the IP. But, i forgot to say that i dont have any control over Client code. – user2245180 May 02 '13 at 20:45
  • Why does keeping a reference hold up a connection? Please explain. – user207421 May 02 '13 at 21:41
  • Because you've made a dubious claim, which has been queried, and you haven't backed it up. – user207421 May 03 '13 at 09:17
  • how would i back this up? if some other thread/ process keeps sockets open they will jam up. did you see the edited answer that points to http://stackoverflow.com/questions/519850/network-programming-to-maintain-sockets-or-not – tgkprog May 03 '13 at 09:50
  • You would back it up by making a plausible statement. You haven't. Keeping a socket open is different from keeping a reference to it, and neither of them causes anything to 'jam up'. What causes things to 'jam up' is *blocking I/O.* The answers in the question you cited are mostly in *favour* of keeping sockets open, and there is nothing there whatsoever about 'jamming up'. Your claim remains unsupported: if I could downvote again, I would do so. – user207421 May 03 '13 at 10:24
  • The idea of storing them in the Hashmap and setting the position to null once i close the conections... what do you think ? – user2245180 May 03 '13 at 12:35
  • @tgkprog If you have a plausible explanation for your claim please provide it. You have singularly failed to do so. Abusing me doesn't constitute proof, or even an answer. – user207421 May 03 '13 at 12:43
  • @user2245180 setting to null wont close the connection. if you must store in a map, you need to store an object like – tgkprog May 03 '13 at 12:48
  • I liked your answer, better store the Object playing the role of Client than the actual socket. and Other thread closing the conections and removing the object from the hashmap, OR the same thread that is inside the "Client Object" can close its own conections and remove itself from the hashmap. Thanks. – user2245180 May 03 '13 at 15:18
  • In regular execution the same thread that the client invokes will close the connection. The daemon reaper of orphans is a fail safe for connections that might be left unclosed for some reason (like there was an error while processing the dark side) etc. So it would inspect all the objects and if an object was created more than x minutes back OR you have some field called lastAccessedDate and that has not changed in more than Y minutes (and your processing code makes sure it updates that to current time every few seconds) then the daemon knows that connection is an orphan and should be closed – tgkprog May 03 '13 at 23:00
0

I'm having a bit of a problem trying to understand what is the flow of the operations, and what exactly you have at disposition. Is this sequence correct?
1. client writes to database (delphi)
2. client writes to server (delphi)
3. server writes to database (java)
4. server writes to client (java)
5. client reads database (delphi)
And the problem is pass 4?

More important: you are saying that there isn't a socket in the Client class, and that you don't have a list of Client too?
Are you able to use the reflection to search/obtain a socket reference from Client?
If you say you don't have the socket, how could it be that you can add that socket in a HashMap?
Last but not least: why do you need to store the socket? Maybe every client opens one connection which is used for multiple requests?

It could be beautiful if all the answers could be conveyed to just one ip:port...

lunadir
  • 339
  • 3
  • 15
  • The sequence is right. I said "i don't have the socket" but i mean in the class that is going to be used to answer. Because i instatiate every Thread without Identifier the sockets are unreachable, at least i create a HashMap or a list of them. I can get the IP and Port of the clients but as far as i know: The IP and Port of a Client Socket is not enough to send/recieve data from it in Java, i wish i was wrong tho. – user2245180 May 06 '13 at 13:15
  • But if you initialize `Client` with a `socket`, couldn't you use for example a linked list of a structure with the `socket` and the `Client`? In that way you would have both of them. You could even keep it ordered by the `hashCode()` of the socket, so that it's faster... If you have to answer manually with a socket to the client, what the `Client` class is doing with it? – lunadir May 06 '13 at 14:24