Trying to find my networking goof

I have a server class which extends Thread.
This class’ run method handles the onReceive for the NIO socket.
I also have a Manager class that extends Thread, whose run method handles sending updates to players by looping thru them all and send each an update packet. I know the idea is to have a single thread, but to do so in this scenario, the players would have to continually send something to get something back if I were to remove the Manager’s thread.
My error, which still haunts me is that chats and only chats have garbage. Text in other packets and all locational data sends fine.

What have I missed here?

WOdl have to see the code, but beware of race conditions. The Select code for instance is definitely NOT thread safe.

wanna see it? ;D

Yep. Can you post a reasonably small example that shows the problem?

The Server class extends thread and has a run method that calls onReceive().


public void onReceive(SocketChannel client, ByteBuffer message) {

	int type = message.getInt();
	switch(type) {
		//other case statements...
		case Constants.MSG_CHAT:

					
		// testing
		manager.sendUniversalMessage(client, message);  // never get this


		// and
		//rawSend(client, message);  // when uncommented, never get this either
		break;

		default:
		break;
	}
}

The manager is the ServerManager class, which extends thread and has the following


// send packet along
public void sendUniversalMessage(SocketChannel client, ByteBuffer b) {
	try
	{
		// send client message

		synchronized(b) { 
			b.rewind();  // so the MSG_CHAT marker is the beginning
		}
		ServerPlayer pl;
		for (Enumeration e = players.elements() ; e.hasMoreElements() ;) { 
			pl = (ServerPlayer)e.nextElement();
			pl.addDataToQueue(b);  // adds to a LinkedList on player
			System.out.println("Sending chat to: " + pl.getAlias()); // I see this watching server
			pl = null;
		}


	}
	catch(Exception e)
	{
		e.printStackTrace();
	}		
}

then later on in the run…


public void run {
	// many other odds and ends like tick the serverplayership for movement and build
	// one giant update packet of all players and positions and add to player's queue..t
	// then the queues are called upon after setting a ServerPlayer object
	for (Enumeration e = players.elements() ; e.hasMoreElements() ;) { 
		pl = (ServerPlayer)e.nextElement();
		if(pl.getClient().isConnected() && pl.isReadyForUpdate()) {
			pl.addDataToQueue(udpacket);
		}
		pl = null;
	}
	// then 
	// send the packets from the players queue
	for (Enumeration e = players.elements() ; e.hasMoreElements() ;) { 
		pl = (ServerPlayer)e.nextElement();
		if(pl.getClient().isConnected()) {
			pl.send();
		}
		pl = null;
	}

}

Now the players send method…all of the data makes it to the queue, I always get login and logout data
and all movement pakcets and the profile packet with text and numbers for the ‘character sheet’ BUT no chat messages ever make it to the player
and the rare ones that do…its all gibberish and garbage characters


public synchronized void addDataToQueue(ByteBuffer b) {
	if(dataQueue == null){
		dataQueue = new LinkedList<ByteBuffer>();
	}
	dataQueue.add(b);
}

public synchronized void send() {
	for(int i=0;i<dataQueue.size();i++) {
		ByteBuffer b = dataQueue.poll();
		if(b == null)
			return;
		try {
			if(b.getInt() == Constants.MSG_CHAT) {
				System.out.println("Sending chat to player"); // i see this on server
			}
			b.rewind();
			client.write(b);
		}
		catch(Exception ioe) {

		}
	}
	return;
}

Everything except chat comes to the players receive method!

the players client class extends thread and has an onReceive as well and in the switch statement I have the following among other thins


	case Constants.MSG_CHAT:
		// get channel id then create mesage

		// this is the text of the message
		line = jenn_toString(message);
		System.out.println("Got chat from server: " + line); // never see this
		Manager.getHUD().getChatPanel().addMsg(line);
		break;

I really need to look at this in mreo detail BUT…

I notice you synchronize b during the rewind and then put it in a queue and go on.
A few quesions…

(a) You put it on the queue outside of the syncrhonize. Is anyoene lse messign with b such that it coudl get changed between when you rewind and when it gets on the queue?

(b) Whats on the queue? Just a pointer to b? If so, could anyone else be messing with it while ist sittign on the queue?

Basically I dont udnerstand why .rewind() is synchronized and nothing else is…

Honestly, it is done that way because I found some sample code that did that. But…as for anything messing with b after the fact, it shouldn’t…It is passed to the method, then into the Queue. Nothing should need to mess with it again.

Okay let me read it over when Im awake (tomorrow) and see what OI can spot!

Thanks!! I can post the source on my site if need be.

doh! made a few changes, ran some test and still cant get the chat portion! What a freaky deaky!! LOL

Let me see if I can explain this right…I just noticed in my code that the server always gets set to 127.0.0.1 and port# ###.
The client is looking for ip 68.12.#.# same port. Obviously this explains why a local user always does well. Could this account for the chat portion not working with connecting from an external source(thru nat router), even though other portions do?

Turns out my setIP() method was not setting the ip and still using the InetSocketAddress§ creator.

Think I found it. I am updateing a LinkedList queue fomr my servermanager for moves every som many seconds. This same queue gets chat messages, since they are all ByteBuffers. While testing some other things, I turned off the move updater and voila, my chat works. Why this works all the time locally and never remotely is still a mystery, but at least I can look for other ways of sending moves.