aspose file tools*
The moose likes Sockets and Internet Protocols and the fly likes Taming the network problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Sockets and Internet Protocols
Bookmark "Taming the network problem" Watch "Taming the network problem" New topic
Author

Taming the network problem

Alan Shiers
Ranch Hand

Joined: Sep 24, 2003
Posts: 237
Hi there,

I've been working on a client/server application and communication between both is strictly character data. I am using xml markup as a medium to contain the data. I've managed to successfully use one approach to solving the problem, but I'm wondering if there is a better solution.

My concern is mainly for the client side app. Here is what I've done so far:

1. Created a class named ReceivingThread extends Thread
2. ReceivingThreads job is to strictly read in any data coming in from the network.
3. I've defined a constant named EOF (End Of File)
4. The process is simple. Every message sent over the network is followed by an EOF constant.
5. The ReceivingThread uses a while loop that continually monitors the data coming in and stores the messages in a StringBuffer which eventually winds up in a ConcurrentLinkedQueue for processing. Messages are read in using the lines:

6. You can see that I'm testing for null on the readLine() statement, however, null never occurs in this case because the Socket never closes. Why? Because I must keep the line open while the client is connected to the server. Instead, within the conditional if block I test for the EOF constant so that I know when to break out of the loop. Breaking out of the loop is necessary in order to examine the message and store it into the queue.

7. You'll notice a call to validateMessage(message) method. Here's the method:

You might well ask, "Why is this method necessary?". In my testing I discovered that the EOF constant doesn't consistantly arrive after each and every message sent out. If multiple messages are being sent simultaneously out onto the network by multiple client instances and each message is followed by an EOF message, occasionally I wind up with all those messages concatonated together before an EOF arrives. Therefore, I had to create this method validateMessage() to split the messages appart before I stored each into the queue. In my way of thinking, I shouldn't have to do that in a perfect world (ha ha).

We cannot rely on the sequencial arrival of packets over the network (this is true), so my solution is the only one I could think of to solve the problem. It seems so much like a bandaid solution though. Perhaps someone knows of a better approach to solving this problem?

Alan
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Originally posted by Alan Shiers:
If multiple messages are being sent simultaneously out onto the network by multiple client instances and each message is followed by an EOF message, occasionally I wind up with all those messages concatonated together before an EOF arrives.


That's odd. A conventional server design would have each client on its own port, serviced by its own thread. Since each client is sending data to different server ports, one should not have messages getting intermixed. How are you sending data from multiple clients to the same server port?


"blabbing like a narcissistic fool with a superiority complex" ~ N.A.
[How To Ask Questions On JavaRanch]
Alan Shiers
Ranch Hand

Joined: Sep 24, 2003
Posts: 237
Originally posted by Joe Ess:


That's odd. A conventional server design would have each client on its own port, serviced by its own thread. Since each client is sending data to different server ports, one should not have messages getting intermixed. How are you sending data from multiple clients to the same server port?


The server, in this case, listens on one port and does indeed create a new thread for every client that logs on. Each client on a seperate Socket. It is setup to broadcast messages, that is, if any one client sends a message, the server broadcasts the message to every other client that is logged in except for the originator of the message.

The client side app, of which there could be many instances running at one time during a session, needs to also listen to any responses from the others who are logged into the server. For instance, one of the important things the client side app does is take a poll of who is logged in. Each client instance replies with critical data such as: userName, clientID, isFacilitator. With those three pieces of info I can create an instance of class Participant and load up a JList of those logged in.

So, think about it. Each client receives a Poll request and replies with those 3 pieces of info all wrapped into an xml message. Each message is sent to the server, which in turn, broadcasts each message to all logged in.
If you have 30 people logged in all sending out a response to a Poll request, that's 30 messages X 30 clients. You can now see that each client instance is now going to have to contend with all these responses symultaneously. This is what I'm working with.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

How are you broadcasting messages? UDP?
I'd just use the same socket the client is attached to (presumably TCP) and have the server "broadcast" by writing incoming messages to each client socket in turn.
Alan Shiers
Ranch Hand

Joined: Sep 24, 2003
Posts: 237
That is what the server is doing. No I'm not using UDP.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

We cannot rely on the sequencial arrival of packets over the network (this is true),


TCP guarantees sequential delivery, at least at the packet level. You must be introducing the message shuffling in your code somewhere.
My guess is that you have multiple threads writing to the client sockets at the same time. IO is not atomic so you get the messages intertwined. You will need to serialize (as in control, not data storage) access to the sockets output streams with locks or queues.
[ December 06, 2007: Message edited by: Joe Ess ]
Alan Shiers
Ranch Hand

Joined: Sep 24, 2003
Posts: 237
Here's how a message is sent in each client instance. A new thread is created and destroyed when it finishes doing its job:



As you can see, the message (xml) is sent followed by an EOF message. All client instances do the same and the server expects this as well. Nowhere else in the client-side app code am I writing out to stream. So, if 30 client instances are responding to a poll request, then that's 30 message responses with an EOF message. At the server multiply that 30 X 30 and you have 900 messages being generated over the network. So each client-side apps ReceivingThread needs to contend with incoming poll responses from everybody. Therefore, what I am getting is multiple xml messages concatonated together before an EOF shows up. This is why I'm having to inspect each message as it arrives and split it up into seperate messages. Even though each client app throws out an EOF after each message, that doesn't guarantee it will arrive before someone elses poll response arrives.

How you can guarantee it is beyond me. I don't understand what it is you mean by introducing locks in this scenario.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Let me drag my soapbox over here. . .OK: Creating short-lived threads is a Bad Idea. Threads are operating system resources and require some nontrivial work to get running: allocating stack space, creating a thread context, creating a thread descriptor and so on. Creating lots of short-lived ones results in a lot of unnecessary churn at the OS level.
Now for your problem. You have these message dispatch objects. You can see where invoking something like:

gets you into trouble, right? You now have 3 threads attempting to write on the same output stream. Presumably when one write call blocks, the thread goes into wait state then the next available thread attempts to write to the socket and the next thing you know, their messages are intertwined.
How about not associating the thread with the message?
[ December 07, 2007: Message edited by: Joe Ess ]
Alan Shiers
Ranch Hand

Joined: Sep 24, 2003
Posts: 237
Your point is well taken. I didn't really think about each instance of the SendingThread as causing unnecessary processing by the OS and taking up Stack space. But it's true. I've elliminated the SendingThread and simply incorportated what it does in a sendMessages(...) method. It works just as well.

When I started this project I consulted a book of mine: Java How To Program by Deitel&Deitel. It has an example in it of how to make a client/server Chat program. I was using their example. Since the chapter is on multithreading they did have a SendingThread class defined. That's where I got that from.
Joe Ess
Bartender

Joined: Oct 29, 2001
Posts: 8927
    
    9

Originally posted by Alan Shiers:
Java How To Program by Deitel&Deitel.


I can't speak to the quality of their code, but if this is their web site, i'd be suspicious. It's practically unusable.
 
 
subject: Taming the network problem