I've been messing a lot with TCP/IP Communication the last few days (Using Java and C#). I understand how it works and am able to use it. My Question is more a code design question, how its done the best and easy way to make a real communication.
For Example ive Built my own Multiuser Chat Server. I want my Communication to be able to decide wather its an Auth request, or a new chat message the ability to get the current user list etc etc.
Ive implemented a few ways on my own, but im not quite happy About that since i think theres a more standard and beauty way to do this.
My first thought was a String with Delimiters wich gets splitted, here is the Example of my Implementation of my Communication in Java:
//The Object-types im Using
clientSocket = new Socket(host, port_number);
_toServer = new PrintStream(clientSocket.getOutputStream());
_fromServer = new DataInputStream(clientSocket.getInputStream());
//Example Commands my Client sends to the server
_toServer.println("STATUS|"); //Gets the Status if server is online or closed (closed can occur when server runs but chat is disabled)
_toServer.println("AUTH|user|pw"); //Sends an auth Request to Server with username and Password
_toServer.println("MESSAGE|Hello World|ALL"); //Sends hello World in the Normal Chat to all Users
_toServer.println("MESSAGE|Hello World|PRIVATE|foo"); //Sends hello World only to the user "foo"
_toServer.println("USERS|GET"); //Request a list of all Connected Users
//Example In the Recieved Message Method where all The Server Messages Get Analyzed
serverMessage = _fromServer.readLine(); //Reads the Server Messages
String action = serverMessage.split("|")[0];
if (action.equals("USERS")) { //Example "USERS|2|foo;bar"
String users[] = serverMessage.split("|")[2].split(";");
}
if (action.equals("MESSAGE")) { //Example "MESSAGE|Hello World|PRIVATE|foo"
if(serverMessage.split("|")[2].equals("ALL") {
//Code and else for private....
}
}
if (serverMessage.equals("STATUS|ONLINE")) {
// Code
// I leave out //Code and } for the next If statements
}
if (serverMessage.equals("STATUS|OFFLINE")) {
if (serverMessage.equals("AUTH|ACCEPTED")) {
if (serverMessage.equals("AUTH|REJECT")) {
Is this the way its normally Done? Ad You See I need to send Statuscodes and Objects Corresponding to the Code. Ive Thought about Writing the Data in Bytes aswell and Implementing a "Decoder for Each Object", Example:
int action = _fromServer.readInt();
//opcodes is just an Enum Holding the corresponding int
switch(action) {
case(opcodes.MESSAGE):
break;
case(opcodes.AUTH):
break;
}
Note that this is more over a general design Question not just for this Chat Server Example, I think im Implementing a little Network Based Console Game just for Practise.
Is there a better way to do this or even an API/Framework?
Thanks in advance!
Essentially you're designing a protocol. There are a number of communication protocols that can handle this, the main one that comes to mind is IRC. I'm sure you can do a web search for tips on how to implement the protocol.
As for extending something like this for a console game, well I would start with implementing IRC, and using that to learn how real communication protocols are written. Once you've done that you can build on it to add your own commands to your framework.
If you are designing a protocol for inter-language communication, I would suggest not to use formated Strings as a means of communication but statusbytes. If you consider for example the design of TCP/IP itself you will find, messages consist of a fixed-format header and a variable payload. That way you always know, that (e.g.) the third byte of the message contains the messagetype, the fifth denotes an errorstate and so on. This makes handling easier.
If you have designed your protocol, you could consider working with explicit MessageObjects on the java-side, in which case you would implement a factory with marshalling and unmarshalling methods for these objects, converting objects from and to messages in your protocol.
If you are all-java you can even spare that effort and use ObjectInputStreams and ObjectOutputStreams on client and Server. If you are not, you might want to take a look at the Google Protocol Buffers: http://code.google.com/intl/de-DE/apis/protocolbuffers/, which do essentially the same for inter-language communication.
If your project grows, you may want to have a look at Netty - it's a framework for dealing with communication code. If your code is simple, you will be better off doing things manually.
As for protocol design, it depends on what is most important for you: performance, extensibility, human-readability, ease of debugging etc. These criteria may oppose each other to some degree, for example high performance may mean preference for binary protocols, but these negatively impact ease of debugging and sometimes extensibility. It's usually a good idea to not reinvent the wheel. Get inspired by existing protocols. If you choose to go binary, don't start from scratch unless you really have to, start with Protocol Buffers. If your app is simple and not aimed at very high performance, use a human-readable protocol which will make your life easier (debugging and testing are possible with standard shell tools such as strace and nc).
I think Apache MINA will help you. http://mina.apache.org/
Building a Java C/S application is really complex, you need to deal TCP, UDP and multi threads programming; MINA can help you for these things.
I think the other part you need is your private chatting protocol, but how about the open sourced IM service like Jabber? :)
Related
We're developing special devices that uses XMPP to talk to each other. A new API i am developing now, should talk to these devices too. The problem i am facing - all these devices are building little groups - for each customer we have... so we will have a chat-room for each group of devices, or, for each of our customer with his bunch of devices ;)
But now.. the api should be able to talk to every device that is connected. I don't need a real broadcast-mechanism - in the end, i will send a message only to one specific device..
But i don't want to login to each chat-room either - running a product with over 40k customers and much more devices, will end in a funny api, that is opening over 40k chat-rooms at startup... even if don't tried this yet, i can't imagine that an app like this will run well... even though we can have millions of customers in a few years.. i don't like solutions that will grow linear with the amount of customers, if you know what i mean :/
Now, basically i'm thinking of a solution, where i just can use the basic XMPPConnection to do my stuff.
MyCustomMessage msg = new MyCustomMessage();
msg.setTo("*"); // don't know what to address, i want to send it to "all"
msg.setFrom("ThatAPI"); // just a string telling that is sent from my java api ;)
msg.setEvent(event); // stuff that is coming through the parameters of the method where this code is inside
msg.setCustomStanza(data); // same here
connection.sendPacket(msg); // my try to send it to all till now..
Somewhere in the Ignite Realtime Forums i have read of one guy who "solved" it, but everything he says is "it's working now, i push my message through the sendPacket of Connection"... ok nice, my attempt of this seems not to work :(
Any better ideas/real implementations how this will work fine?
Basically i start to think that XMPP will not be the best technology to achieve something like this at all - i wish i could have a real/basic socket-implementation where something like this would be piece of cake.. But i can't choose - the third-party-system has implemented XMPP already... not enough time to change all of this... Just if you're wondering why we try this on XMPP..
You seem to have some conflicting requirements in that you want to send to all devices now, but only 1 specific device later. Are both models required at the same time, or do you plan on switching? How either is done would be different solutions.
As for your current approach, I think pubsub would make more sense than your chatroom approach, as that is oriented to generic message passing to subscribers.
You could set up a pubsub node per customer to send messages to all
of their devices.
As for a broadcast to all, you can make all devices
subscribe to a single pubsub node.
Thus you control broadcast and group messages by sending to the appropriate pubsub node.
For sending to a specific device, that is just a sendPacket to the specific entity, nothing really special there.
I have a chat program implemented in Java. The client can send lots of different types of information to the server (i.e, Joins the server and sends username, password; requests a private chat with another user on the server, disconnects from the server, etc).
I'm looking for the correct way to have the server/client differentiate between 'text' messages that are just meant to be chat text messages sent from one client to the others, and 'command' messages (disconnect, request private chat, request file transfer, etc) that are meant for the server or the client.
I see two options:
Use serialized objects, and determine what they are on the receiving end by doing an 'instanceof'
Send the data as a byte array, reserving the first N bytes of the array to specify the 'type' of the incoming data.
What is the 'correct' way to do this? How to real protocols (oscar, irc) handle this situation?
I've googled around on this topic and only found examples/discussions centering on simple java chat applications. None that go into detail about protocol design (which I ultimately intend to practice).
Thanks to any help...
Second approach is much better, because serialization is a complex mechanism, that can be easily used in a wrong way (for example you may bind yourself to internal content of a concrete serialized class). Plus your protocol will be bound to JVM mechanism.
Using some "protocol header" for message differentiation is a common way in network protocols (FTP, HTTP, etc). It is even better when it is in a text form (people will be able to read it).
You typically have a little message header identifying the type of content in all messages, including standard text/chat messages.
Either of your two suggestions are fine. (In your second approach, you probably want to reserve some bytes for the length of the array as well.)
So I recently followed this tutorial on making a basic chatroom in Java. It uses multithreading and is a "connection-oriented" server. I was wondering how I could use the same Sockets and ServerSockets to send, say, the 3d position of an object instead of just a string?
Currently, the basic chatroom system just sends a string to the server and then the server sends it to all connected clients. What I want is to be able to have a client change the position of an object (most likely their character), and send the change of position to the server. Then (I would imagine) the server would send that change in position to each of the clients connected to it, and each client would in turn render this object at its new position.
I was wondering what the best way to do something like this was?
Would it be to send a string and have the server parse it into a coordinate?
Can I write more than one thing to a DataOutputStream at once?
I feel like I may have explained this poorly, so please ask some clarifying questions.
Thanks!
Create a Domain Object Model for your coordinate system. Then represent the changes to the positions using the objects in the above model. Serialize them into a transportable string like XML, JSON etc. Then unmarshall/deserialize the String to the original object and act upon them.
This separates your transport layer (using sockets to bradcast stuff) from the actual business logic (placement of objects) and the system becomes extendible.
I want to write an application for my android phone to control it via wlan. That should contain its camera abilities.
Is there any elegant method to send live pictures and other information in one socket "at the same time"? My idea is to let the server accept more than one client: the first for life images, the second for information, third for audio streaming...
It should work like skype: you can call people and chat at the same time with one connection. How can I implement something like that?
I doubt multiple sockets would do you any good (unless Android makes it really hard to put data from multiple sources into the same stream). Just send everything sequentially in the same stream, with a tag in front to identify each type of data. The fancy name for this is "time-division multiplexing".
Multiple sockets might make sense if you get into fancy tweaking to, say, give more priority to realtime streams, but I have a feeling that shouldn't be necessary.
I have a simple ajax game between 2 users with java backend (tomcat, spring). I need some good way of notifying one user that his opponent made a turn. Now all communication is done through database and waiting for opponent to finish his turn looks like this:
while(!timeout && !opponentIsDone) {
//...get the game record from db and check if opponent made turn
Thread.sleep(100);
}
Can I somehow get rid of this loop with sleep() and get instantly notified without a delay (but with timeout)? I can probably make some global static var and communicate through it, but I still will need similar loop only maybe timeout will be smaller.
I can't just call some method once the turn is done because it is all need to go to the browser through ajax and I can't push data there, only pull. So I need to have process that waits for the opponent.
I am looking for some light and simple solution.
Thanks.
You may want to look into Tomcat's advanced IO (Comet) support.
http://tomcat.apache.org/tomcat-6.0-doc/aio.html
I think you're looking for the Distributed Events (aka Subscriber/Publisher) pattern, and I believe Dojo Framework has implemented it:
http://ajaxpatterns.org/Distributed_Events
There are many ways to push notifications to a web client. Gmail's IM client is an excellent example of this sort of thing. This is often accomplished by holding an open HTTP connection in some manner, and this family of techniques is referred to as COMET. Wikipedia has an article on it, and there are blogs dedicated to the subject ( http://cometdaily.com/ ).
Even if you didn't use this technique, there are still many improvements you can make to the algorithm you identified in your question. One way would be to use a wait/notify sort of pattern or a subscriber/publisher approach. Another would be to return a "waiting for other player to make a turn" page immediately, and have that page automatically refresh every few seconds until the other player has taken his turn.
I think the solution you're looking for is COMET-style notification, though.
If you had a global static var of some sort, you could use a java.util.concurrent.BlockingQueue<T>
BlockingQueue<Turn> handoff = new ArrayBlockingQueue<Turn>(1);
// opponent thread
handoff.offer(myTurn);
// other thread can use
Turn otherTurn = handoff.poll( 90, TimeUnit.SECONDS );
if ( otherTurn == null )
// then no turn made
You can easily make the people wait for each other by using SynchronousQueue instead of ArrayBlockingQueue.
and of course it doesn't need to be global static -- it could be anything accessible to both users.
flex/flash has a real-time chatroom system (using remote-object programming).
you have to install BlazeDS (free) http://opensource.adobe.com/blazeds/, it comes with sample application. This is called AMF technology. I think Spring does support this AMF in one way or another.
http://www.adobe.com/devnet/livecycle/articles/blazeds_spring.html
http://blog.springsource.com/2008/12/17/using-spring-blazeds-integration-m1/
It's good for Flash based website. However, if you don't want to use flash, i think u can hide it or make it small enough, just to use it as a communication channel on your page.
Perhaps you have to find a way to notify your webpage/javascript after flash receive data from server.
Yeah, I know this method is a bit hacky, and it's not a clean way of doing thing :) just to provide an alternative for you.
DWR (Direct Web Remoting) is a package that allows you to make Java methods on the server directly available to Javascript (by creating a proxy). It has a feature called "Reverse Ajax" that is an easy way to handle push scenarios.
Perhaps consider Jetty Continuations if you aren't locked into Tomcat?
http://bill.burkecentral.com/2008/11/12/buggybroken-tomcat-6-comet-nio-apis/ has some discussion about Tomcat NIO