I have a project that consists of:
Java server: I accept the connection of N numbers of clients through multithreading.
Client (c++): connects to the Java server.
The dilemma I'm having is how can I send information to the client (from Server) about X and at the same time while that happens make another request. To understand my question better I will give an example:
example: Imagine that I am sending a file from the java server to the client in c++ and while this sending of bytes from the server is taking place, I want to send an echo to the client from the server and receive a response simultaneously while the sending of the file is happening. Is this possible?
2 example: Another case that I would like to address is what would happen if I am receiving bytes on the server from the client and I make another request (echo), so the same socket would be listening x2 (can i read bytes from the same socket simultaneously? What would happen then?):
case 1: receiving bytes
.case 2: listening to the echo
My solution so far has been to use Executors.newSingleThreadExecutor, which allows me to handle each "action" in order one by one. My goal is to be able to perform the actions asynchronously, so that I don't have to wait for another one to finish. How can I achieve this theoretically speaking?
As you're anyway dealing with Java talking to C++, you might as well use something like Google Protocol Buffers to implement an application layer protocol (as Steffen Ullrich suggests), and definitely do not have multiple server threads sending data to a single client.
With GPB, you can define a set of messages, something like (pseudo GPB syntax)
message FileFragment
{
string filename = 1,
integer fragmentFilePosition = 2,
bytes fragmentData = 3
}
message Echo
{
integer echoNum = 1
}
message Protocol
{
oneof
{
FileFragment fragment = 1,
Echo echo = 2,
}
}
With this, you'd create and send Protocol objects through the socket. The client receives those, and either stuffs the fragment data into a file at the position indicated, or deals with the echo.
There are other heterogenous serialisation technologies - ASN.1 is my preferred option, XML can be made to work if you can get good tools, JSON (though that might be a bit tricksie in C++?). I'd default to ASN.1, but GPB is free and enjoys excellent language support.
Java itself is sometimes a nuissance because (AFAIK) it doesn't support unsigned integer types, but as you're in control of both server and client source code (and therefore in control of the procotol between them and the schema that defines it), you can live with it. The nuissance comes if someone else has defined a protocol containing an unsigned 64bit integer type, which then cannot be easily handled in Java.
With Google Protocol Buffers, the wireformat is not self-demarcating, so if you just stuff serialised Protocol objects down the socket the client cannot tell when one ends and another begins. So you'll have to do that separately. A lot of people use something like ZeroMQ (which is message-orientated, not stream-orientated) for this purpose instead of a raw socket.
If you really wanted separate threads sending different Protocol objects through to the client, you'll need a way of guarding against both threads trying to access the socket at the same time (ZeroMQ sockets are not in themselves thread safe), a mutex of some sort.
Related
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.
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
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.
the servers have a protocol to either take new jobs or check status of old jobs. Client pools the server periodically.
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)
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...
I have an application where I have to send Signals and Data between two entities.
Which way is best practice and why?
Open 4 sockets, 2 for signals in both directions and 2 for data in both directions
Open 2 sockets each for data and signals
Just open 1 socket and filter for signals and data
First of all sockets are full-duplex, i.e. you don't need a separate socket (connection) for sending and receiving.
Secondly, it's hard to tell without going into more details. However knowing the history of HTTP (one connection for commands/headers and data) and FTP (separate connections for commands and data) seems like HTTP designers made a better choice. Two connections is more code to maintain, also some firewalls don't like hanging, idle FTP command connection when large portions of data are transferred.
So, go for one connection, it's easy to distinguish between signals and data (flag, header, etc.) Also incoming and outgoing channel is completely orthogonal.
Why can't you just have 1 socket for all data and 1 socket for all signals. You can send signals to the remote entity while reading signals from the remote entity from the same socket. This is sort of like how FTP (non-passive) works, you have a control connection and then one used for the actual data transfer.
Having 4 sockets seems overkill, but I don't know the context of what the signals or data are.
If you don't mind more code to decode the network communication, you can definitely do it all in one socket. It'll require more thought into the actual communication, a better "protocol" if you will. Both the 2 socket and 1 socket model are fine.
There is a possible "middle way" - use JBoss remoting or similar to multiplex several virtual sockets on top of one real one. That way you can keep the data and control channels separate at the application level but still require only one TCP port (and thus at most one firewall hole) at the operating system level.
Another way: use a dedicated middleware, built for realtime application like 0MQ.
To instantiate ØMQ:
Jzmq obj = new Jzmq (hostname);
Where hostname is name or IP address of the box where zmq_server is running.
To create wiring, createExchange, createQueue and bind functions can be used. For detailed description of how wiring mechanism works have a look here.
int eid = obj.createExchange ("E", Jzmq.SCOPE_GLOBAL, "10.0.0.1:5555");
obj.createQueue ("Q", Jzmq.SCOPE_GLOBAL, "10.0.0.1:5556");
obj.bind ("E", "Q");
Sending a message is pretty straightforward. Message is supplied in form of byte array:
byte msg [] = {1, 2, 3, 4, 5, 6};
obj.send (eid, msg);
Receiving a message is even more simple:
byte [] msg = obj.receive ();
Full sample available here.
I'm implementing this example as I want to broadcast to multiple clients. While trying to use the socket to send another object(which has been serialised), I'm getting an error which says that socket(in the example) can't send the object via it. Can't a datagram socket send/receive objects also?
Not in general, no. Datagram packets are generally relatively small - you could try serializing your object to a ByteArrayOutputStream wrapped in an ObjectOutputStream, and then try to send the byte array afterwards - but you may well find it gets too big very quickly.
Using a more efficient serialization format such as Protocol Buffers will probably allow you to get more information in a single packet, but typically you'd want to serialize to a stream instead of to a single packet... and as soon as you start trying to put a stream-based protocol over a datagram-based protocol - well, you end up with TCP reasonably quickly, as soon as it has to be reliable.
If you can give us more details of what you're trying to do (including reliability constraints - how serious is it if a packet is lost?), we may be able to help you more.
Your best bet is to either use TCP or another library such as jGroups
JGroups is a toolkit for reliable multicast communication.
In a socket-based application (client/server), I want to make the server perform as a proxy(manager) to handle several clients, and to get the message from one client and send it to the client, identified by an ID.
How can I know the required client running on different thread, how can I get the socket of the associate client that the id represents?
Just keep an in-memory hashmap of some sort of client-id to the java.net.Socket object that represents that client's socket. You need to come up with some way of assigning client IDs, either client supplied, or server-supplied through some authorization scheme.
When a message comes in for a client ID, grab the socket from the map and send it a message. This map needs to be stored in a singleton-type object, and needs to be properly synchronized. Use a concurrent hash map. Also, socket reads and writes would need to be synchronized if you're going multi-threaded.
I have posted some example code as a github gist. It's a bit different than I explained above. I don't store sockets in the map, I store client handlers which have the socket. Also, socket reads don't need synchronization: each clients has its own thread which is the only thread reading from the socket. Socket writes do need to be synchronized though, because the thread of the sending client is writing to the socket of the receiving client.
You're probably better off using something like JBoss Netty rather than rolling your own though.
you can keep a lot of information about ID so each time it connects you get like the ip and save the thread it is running on and then you use like a hashmap to link the id to all that info then you can easily get the thread it is running on and send the information to the correct client
Save the messages to be delivered into a database, and make your threads check the database for new messages to be delivered to "their" clients on a regular basis.
If you do not want a dedicated database for the messages, build a flat file with simple ClientID->Socket mappings and use it like a "telephone book" kind of lookup system. Depending on the amount of clients you are planning to add, each thread could pre- and regularily reload such a file into it's memory for faster access...
I am writing the code for a server that would help two different applications in different platforms communicate with each other. To visualize it a bit it would be something like this :
App1<------>Server<------>App2
What server does is rear var1 from app2, write it to app1, then read var2 from app1 and write it to app2. Like this :
while(true){
var1 = app2stream.readInt();
app1stream.writeInt(var1);
var2 = app1stream.readDouble();
app2stream.writeDouble(var2);
}
My problem is that at some point i have this code at my server :
app1.accept();
app2.accept();
What this means is that no matter what, and given the fact that the server is always running, app1 is the one that should connect first since app1.accept() is a blocking method.
Is there any way around this? It would be great to allow the two applications to connect to the server regardless of who "came" first and then wait for the server to proceed with the above code. Can i use threads just for the accept() part and then pass the streams to the other thread? I read a bit about channels but got a bit buffled, any examples would be great.
Use NIO
It allows you to do non-blocking sockets (including accept) using the Selector class.
Basically, it gives you much more native access to the system libraries and the ability to handle your task without having to multi-thread.
Only have one accept call, and one server socket. You can make the determination which app has connected once they connect. If you can't get it from the connection details, have them send an authcode (probably a good idea anyway) which you can map to your app.
You should probably treat them both the same unless they say otherwise.
For example when the each socket connects send a "what client?" message.
Then check whether the client responds with 1 or 2.
If both respond with 1 or something just disconnect both.
I think the "standard" way to do this is to have the server listening on a port, and when a message comes in, immediately spin off a new thread to handle it, then go back to listening for another message. Then, as Glowcoder says, make all the connections in the same loop and make it figure out which is which after connecting.
I suppose the alternative is to have multiple threads, each listening on different ports. I've never tried to do that, I'm not sure if one would block until a connection was made and so you'd never get to the other thread.