implementing network

You dont HAVE to block, you can use selectNow.

However most people throw off ONE thread to handle the selctor and allow it to block.

The key is thats one thread for ALL sockets, not a thread PER socket liek you would have with java.net.

Just as I thought, tnx.

OK, I got the server working (I thought) and I wrote a small client just to connect and pass some data for server to println() just to see if it works.
First, is my client OK? I wrote it completly myself, looking only at java docs. Did I forgot, like, to close something?

public class Klijent {
	public static final int PORT = 23;
	private InetSocketAddress address;
	private byte[] ip_address;
	private ByteBuffer readBuffer, writeBuffer = ByteBuffer.allocate(1024);

	public Klijent() {
		ip_address = new byte[] {127, 0, 0, 1};
		try {
			address = new InetSocketAddress(InetAddress.getByAddress(ip_address), PORT);	
		} catch (Exception e) {
			System.out.println(e);
		}
		System.out.print("Attempting to connect...");
		try {
			SocketChannel s_channel = SocketChannel.open(address);
			writeBuffer.putChar('K');
			writeBuffer.putChar('o');
			writeBuffer.putChar('v');
			writeBuffer.putChar('a');
			writeBuffer.put((byte)256);
			s_channel.write(writeBuffer);
			System.out.println("successful");
			s_channel.close();
		} catch (Exception e) {
			System.out.println("failed");
			System.out.println(e);
		}		


	}
	public static void main(String[] args) {
		new Klijent();
	}
}

Next, the open(adress) method throws some Exception if it cannot establish a connection, so I tried to put only that statement in try / catch block like this:

try {
	SocketChannel s_channel = SocketChannel.open(address);
} catch (Exception e) {
	System.out.println("failed");
	System.out.println(e);
}
. . . 
s_channel.write(writeBuffer);

but than it complains that it can’t find s_channel… ok I’m missing some basic java knowlage here, why when it’s in try block it ignores it’s creation? I wanted to test if connection was successful with (if s_channel).isConneced() for writing “successful” or “failed” to console but I had to do it like in first part.

Finally, this is all fine, but where do I get the option of using TCP or UDP? I wanted to do it with UDP since the game is so simple I can send complete status in every packet.
Thank you.

variables declared in a block are not visible in parent blocks(the block that encapsulates the block / the block that the other block where it’s declared in)

code blocks can be anything from a class to vanilla ‘{}’ (don’t actually know the technical name of ‘{}’ , Jeff?)
read up on variable scopes.


SocketChannel s_channel;
try {
s_channel = SocketChannel.open(address);
} catch (Exception e) {
System.out.println("failed");
System.out.println(e);
}
. . .
s_channel.write(writeBuffer);

works, the scope of the variable is visible from where it was declared till the end of the block, but also in the blocks declared in that block (the try block as well as the catch block)

on an other note avoid catching too genetric exceptions it leaves for very time consuming debugging.

I know about scoping… just didn’t hope it applies on try catch block also since then you would need to put everything in the block (like in my code), not only statement that throws it. It just dosen’t feel right… like if I had 2 more pages of code that involves that channel with simple operations, it would still have to be in the block.
I like to think about “{}” as sets, since I’m mathematician wannabe.
About generic exceptions… if I print them I would see precisely what exception is thrown anyway, is there something more to pay attention?

what is wrong in my client is that I forgot to flip() it before sending it. My initial though that whole buffer is sent, but of course it came to me that sending whole buffer every time even if you have only few bytes stored is stupid. It wont work without flip, it just send the rest of the buffer you didn’t fill (since position is after bytes you wrote, and limit is capacity).

add writeBuffer.flip() before s_channel.write(writeBuffer) if anyone else plans to use the code.

methodes should be kept short from a maintanable code perspective to allow your code to be reuseable at all it also requires it. and there are more then enough tools avail to you to do so.

thats because your only printing te exception nowonce you start actually recovring from an exception, it gets quite differend.

Still, I didn’t get reply on most important question to me:
when coding that way (channels), where do I have the choice for TCP or UDP?
When using “SocketChannel.open(address)” I guess it’s TCP since it connects to something.

SocketChannel is for TCP only. If you want to do UDP you’ll need to use DatagramChannel.

-Matt Hicks

Thanks Matt… I should have guess it’s something like that.

In my server application, I don’t know where exactly to put channel.close() statement. There is no registering close event on connection with selector, so how do you know when client has closed connection or connection broke? In some tutorials channel is closed when number of bytes read is zero or less, is this right? In java docs it says read() can possibly return zero, but not in what situations or what it means, and it says that can return -1 if has reach end-of-stream. Again I don’t know what that means exactly so I’m not quite comfortable with closing channel after. Thank you.

btw. a funny thing: :slight_smile: if I don’t close the channel in server, after client finishes (closes his channel, disconnects) server starts receiving events non-stop, clottering cpu, even foobar stops playing :slight_smile:

Typically, you would want the client to send a message to the server telling it that it wants to disconnect. If the connection terminates abruptly you should receive an exception. The way I deal with this in UDP was to have my own “expiration” for clients that don’t tell the server that they’re disconnecting and it will remove that client forcefully.

-Matt Hicks

Yeah, quit message… ok.
But in abnormal drop of connection, I don’t get Exception using SocketChannel. Client, telnet (also testing with it) or whatever disconnects, closing SocketChannel on his side, … and server goes beserk with events. Since TCP maintains connection alive I have expected something like Exception or closing event… but java docs tell so little and I’m tired of reading those few tutorials there are online. I can’t implement timeout since server is bombed with events immidietly. Hmm… now I started to wonder… what kind of event is that anyway? Maybe it’s close event hidden in read event form! Got to go test it!

Edit: I printed out bits and it’s event for OP_READ, but buffer is empty. So when channel.read(readBuffer) returns 0 or -1 it is sign that connection is down and to close channel afterall. Java doc is so missguiding about this, they could wrote that also, not just techinical crap.

On your system for that situation.

This sounds liek something that would be very OS dependant so I would not count on it unless you actually test it on all your targets,.

And OS dependant behavior is never Javadoc’d for that reason.

dang… you’re possibly right. I’m using Win XP btw.
So does anyone actually knows how to test if connection has been closed on other side?

Like I said previously, I just handle timeouts instead (each machine sends NOOPs if no message has been broadcast over that connection for a while so a timeout doesn’t occur because of lack of activity). You will get an exception if you try to send a message back to the closed connection and that can also be a way to determine its closed state.

-Matt Hicks

Jeff, it may sound like OS-specific behaviour, but it’s not.

The SocketChannel javadoc:

[quote]public abstract long read(ByteBuffer[] dsts,
int offset,
int length)

Returns:
The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream
[/quote]
When the channel is closed while writing, you get an IOE
When reading, you get the remaining bytes, then -1
When idling, the channel becomes readable, then returns -1 on read.

Riven,

I think what Jeff was conveying was the 0 or -1 when the connection is closed, not just when the end of that particular stream has been reached.

Detecting when the socket is closed on reading is not something you can reliably do since it’s a passive operation.

-Matt Hicks

I think Riven was saying the channel becomes readable, i.e. the select() returns the key as “readable” - so its not really passive since you’ll have something blocking on select() or polling on selectNow() somewhere. When the socket gets flagged as readable you go and read it and the -1 is returned - since you’ve been told the channel is readable and that infact a -1 is returned you now know the channel is dead.

Kev

Indeed, it’s not passive!

I said: “the channel becomes readable”, which is active.

My mistake.

I might go back and update my code to use that instead. ::slight_smile:

-Matt Hicks