Archive for October, 2006

The Pipe class creates a pair of Channel

Tuesday, October 31st, 2006

public static abstract class SourceChannel extends AbstractSelectableChannel implements ReadableByteChannel, ScatteringByteChannel public static abstract class SinkChannel extends AbstractSelectableChannel implements WritableByteChannel, GatheringByteChannel } Figure 3-11. A pipe is a pair of looped channels An instance of Pipe is created by invoking the Pipe.open() factory method with no arguments. The Pipe class defines two nested channel classes to implement the pipeline. These classes are Pipe.SourceChannel (the read end of the pipe) and Pipe.SinkChannel (the write end of the pipe). These Channel instances are created when the Pipe object is created and can be fetched by calling the source() and sink() methods, respectively, on the Pipe object. At this point, you may be wondering what pipes are useful for. You can’t use Pipe to set up a Unix-like pipe between operating system-level processes (you can use SocketChannel for that). The source and sink channels of Pipe provide functionality similar to java.io.PipedInputStream and java.io.PipedOutputStream but with full channel semantics. Notice that SinkChannel and SourceChannel both extend from AbstractSelectableChannel (and thus SelectableChannel), which means that pipe channels can be used with selectors (see Chapter 4). Pipes can be used only to pass data within the same JVM. There are far more efficient ways of passing data between threads, but the advantage of using pipes is encapsulation. Producer and consumer threads can be written to the common Channel API. The same code can be used to write data to a file, socket, or pipe, depending on the type of channel it’s given. Selectors can be used to check for data availability on pipes just as easily as on socket channels. This might allow a single consumer thread to efficiently collect data from multiple channels, in any combination of network connections or local worker threads, using a single Selector. The implications for scalability, redundancy, and reusability are significant. Another useful application of Pipes is for testing. A unit-testing framework can connect a class to be tested to the write end of a pipe and check the data that comes out the read end. It can also set up the class being tested on the read end of the pipe and write controlled test data to it. Both scenarios can be very useful for regression testing. 123
Note: If you are looking for best quality webspace to host and run your tomcat application check Vision tomcat hosting services

The Pipe class creates a pair of Channel

Tuesday, October 31st, 2006

The amount of data the pipeline holds is implementation-dependent. The only guarantee is that the bytes written to the SinkChannel will reappear on the SourceChannel in the same order. Example 3-11 demonstrates how pipes are used. Example 3-11. Worker thread writing to a pipe package com.ronsoft.books.nio.channels; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.channels.Pipe; import java.nio.channels.Channels; import java.util.Random; /** * Test Pipe objects using a worker thread. * * Created April, 2002 * @author Ron Hitchens (ron@ronsoft.com) */ public class PipeTest{ public static void main (String [] argv) throws Exception { // Wrap a channel around stdout WritableByteChannel out = Channels.newChannel (System.out); // Start worker and get read end of channel ReadableByteChannel workerChannel = startWorker (10); ByteBuffer buffer = ByteBuffer.allocate (100); while (workerChannel.read (buffer) >= 0) { buffer.flip(); out.write (buffer); buffer.clear(); } } // This method could return a SocketChannel or // FileChannel instance just as easily private static ReadableByteChannel startWorker (int reps) throws Exception { Pipe pipe = Pipe.open(); Worker worker = new Worker (pipe.sink(), reps); worker.start(); return (pipe.source()); } // —————————————————————– /** * A worker thread object which writes data down a channel. 124
Note: If you are looking for best quality webspace to host and run your tomcat application check Vision tomcat hosting services

The Pipe class creates a pair of Channel

Tuesday, October 31st, 2006

The Pipe class creates a pair of Channel objects that provide a loopback mechanism. The two channels’ far ends are connected so that whatever is written down the SinkChannel appears on the SourceChannel. Figure 3-11 shows the class hierarchy for Pipe. package java.nio.channels; public abstract class Pipe { public static Pipe open() throws IOException public abstract SourceChannel source(); public abstract SinkChannel sink(); 122
Note: If you are looking for best quality webspace to host and run your tomcat application check Vision tomcat hosting services

remoteHosts.add (sa); } } // ————————————————————– public static

Tuesday, October 31st, 2006

} try { TimeServer server = new TimeServer (port); server.listen(); } catch (SocketException e) { System.out.println (”Can’t bind to port ” + port + “, try a different one”); } } } 3.6 Pipes The java.nio.channels package includes a class named Pipe. A pipe, in the general sense, is a conduit through which data can be passed in a single direction between two entities. The notion of a pipe has long been familiar to users of Unix (and Unix-like) operating systems. Pipes are used on Unix systems to connect the output of one process to the input of another. The Pipe class implements a pipe paradigm, but the pipes it creates are intraprocess (within the JVM process) rather than interprocess (between processes). See Figure 3-10. Figure 3-10. The Pipe family tree 121
Note: If you are looking for cheapest and affordable webspace to host and run your servlet application check Astra servlet hosting services

remoteHosts.add (sa); } } // ————————————————————– public static

Tuesday, October 31st, 2006

remoteHosts.add (sa); } } // ————————————————————– public static void main (String [] argv) throws Exception { TimeClient client = new TimeClient (argv); client.sendRequests(); client.getReplies(); } } The program in Example 3-10 is an RFC 868 time server. This code answers requests from the client in Example 3-9 and shows how a DatagramChannel binds to a well-known port and then listens for requests from clients. This time server listens only for datagram (UDP) requests. The rdate command available on most Unix and Linux systems uses TCP to connect to an RFC 868 time service. Example 3-10. DatagramChannel time server package com.ronsoft.books.nio.channels; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.DatagramChannel; import java.net.SocketAddress; import java.net.InetSocketAddress; import java.net.SocketException; /** * Provide RFC 868 time service (http://www.ietf.org/rfc/rfc0868.txt). * This code implements an RFC 868 listener to provide time * service. The defined port for time service is 37. On most * unix systems, root privilege is required to bind to ports * below 1024. You can either run this code as root or * provide another port number on the command line. Use * “-p port#” with TimeClient if you choose an alternate port. * * Note: The familiar rdate command on unix will probably not work * with this server. Most versions of rdate use TCP rather than UDP * to request the time. * * @author Ron Hitchens (ron@ronsoft.com) */ public class TimeServer{ private static final int DEFAULT_TIME_PORT = 37; private static final long DIFF_1900 = 2208988800L; protected DatagramChannel channel; 119
Note: If you are looking for cheapest and affordable webspace to host and run your servlet application check Astra servlet hosting services

remoteHosts.add (sa); } } // ————————————————————– public static

Tuesday, October 31st, 2006

public TimeServer (int port) throws Exception { this.channel = DatagramChannel.open(); this.channel.socket().bind (new InetSocketAddress (port)); System.out.println (”Listening on port ” + port + ” for time requests”); } public void listen() throws Exception { // Allocate a buffer to hold a long value ByteBuffer longBuffer = ByteBuffer.allocate (8); // Assure big-endian (network) byte order longBuffer.order (ByteOrder.BIG_ENDIAN); // Zero the whole buffer to be sure longBuffer.putLong (0, 0); // Position to first byte of the low-order 32 bits longBuffer.position (4); // Slice the buffer; gives view of the low-order 32 bits ByteBuffer buffer = longBuffer.slice(); while (true) { buffer.clear(); SocketAddress sa = this.channel.receive (buffer); if (sa == null) { continue; // defensive programming } // Ignore content of received datagram per RFC 868 System.out.println (”Time request from ” + sa); buffer.clear(); // sets pos/limit correctly // Set 64-bit value; slice buffer sees low 32 bits longBuffer.putLong (0, (System.currentTimeMillis() / 1000) + DIFF_1900); this.channel.send (buffer, sa); } } // ————————————————————– public static void main (String [] argv) throws Exception { int port = DEFAULT_TIME_PORT; if (argv.length > 0) { port = Integer.parseInt (argv [0]); 120
Note: If you are looking for cheapest and affordable webspace to host and run your servlet application check Astra servlet hosting services

import java.util.List; import java.util.LinkedList; import java.util.Iterator; /** *

Tuesday, October 31st, 2006

// Some replies haven’t shown up yet System.out.println (”Received ” + replies + ” of ” + expect + ” replies”); } } // Print info about a received time reply protected void printTime (long remote1900, InetSocketAddress sa) { // local time as seconds since Jan 1, 1970 long local = System.currentTimeMillis() / 1000; // remote time as seconds since Jan 1, 1970 long remote = remote1900 - DIFF_1900; Date remoteDate = new Date (remote * 1000); Date localDate = new Date (local * 1000); long skew = remote - local; System.out.println (”Reply from ” + sa.getHostName() + “:” + sa.getPort()); System.out.println (” there: ” + remoteDate); System.out.println (” here: ” + localDate); System.out.print (” skew: “); if (skew == 0) { System.out.println (”none”); } else if (skew > 0) { System.out.println (skew + ” seconds ahead”); } else { System.out.println ((-skew) + ” seconds behind”); } } protected void parseArgs (String [] argv) { remoteHosts = new LinkedList(); for (int i = 0; i < argv.length; i++) { String arg = argv [i]; // Send client requests to the given port if (arg.equals ("-p")) { i++; this.port = Integer.parseInt (argv [i]); continue; } // Create an address object for the hostname InetSocketAddress sa = new InetSocketAddress (arg, port); // Validate that it has an address if (sa.getAddress() == null) { System.out.println ("Cannot resolve address: " + arg); continue; } 118

Hint: If you are looking for very good and affordable webspace to host and run your tomcat hosting application check Virtualwebstudio tomcat web hosting provider

import java.util.List; import java.util.LinkedList; import java.util.Iterator; /** *

Tuesday, October 31st, 2006

import java.util.List; import java.util.LinkedList; import java.util.Iterator; /** * Request time service, per RFC 868. RFC 868 * (http://www.ietf.org/rfc/rfc0868.txt) is a very simple time protocol * whereby one system can request the current time from another system. * Most Linux, BSD and Solaris systems provide RFC 868 time service * on port 37. This simple program will inter-operate with those. * The National Institute of Standards and Technology (NIST) operates * a public time server at time.nist.gov. * * The RFC 868 protocol specifies a 32 bit unsigned value be sent, * representing the number of seconds since Jan 1, 1900. The Java * epoch begins on Jan 1, 1970 (same as unix) so an adjustment is * made by adding or subtracting 2,208,988,800 as appropriate. To * avoid shifting and masking, a four-byte slice of an * eight-byte buffer is used to send/recieve. But getLong() * is done on the full eight bytes to get a long value. * * When run, this program will issue time requests to each hostname * given on the command line, then enter a loop to receive packets. * Note that some requests or replies may be lost, which means * this code could block forever. * * @author Ron Hitchens (ron@ronsoft.com) */ public class TimeClient{ private static final int DEFAULT_TIME_PORT = 37; private static final long DIFF_1900 = 2208988800L; protected int port = DEFAULT_TIME_PORT; protected List remoteHosts; protected DatagramChannel channel; public TimeClient (String [] argv) throws Exception { if (argv.length == 0) { throw new Exception (”Usage: [ -p port ] host …”); } parseArgs (argv); this.channel = DatagramChannel.open(); } protected InetSocketAddress receivePacket (DatagramChannel channel, ByteBuffer buffer) throws Exception { buffer.clear(); // Receive an unsigned 32-bit, big-endian value return ((InetSocketAddress) channel.receive (buffer)); } 116

Hint: If you are looking for very good and affordable webspace to host and run your tomcat hosting application check Virtualwebstudio tomcat web hosting provider

import java.util.List; import java.util.LinkedList; import java.util.Iterator; /** *

Tuesday, October 31st, 2006

// Send time requests to all the supplied hosts protected void sendRequests() throws Exception { ByteBuffer buffer = ByteBuffer.allocate (1); Iterator it = remoteHosts.iterator(); while (it.hasNext()) { InetSocketAddress sa = (InetSocketAddress) it.next(); System.out.println (”Requesting time from ” + sa.getHostName() + “:” + sa.getPort()); // Make it empty (see RFC868) buffer.clear().flip(); // Fire and forget channel.send (buffer, sa); } } // Receive any replies that arrive public void getReplies() throws Exception { // Allocate a buffer to hold a long value ByteBuffer longBuffer = ByteBuffer.allocate (8); // Assure big-endian (network) byte order longBuffer.order (ByteOrder.BIG_ENDIAN); // Zero the whole buffer to be sure longBuffer.putLong (0, 0); // Position to first byte of the low-order 32 bits longBuffer.position (4); // Slice the buffer; gives view of the low-order 32 bits ByteBuffer buffer = longBuffer.slice(); int expect = remoteHosts.size(); int replies = 0; System.out.println (”"); System.out.println (”Waiting for replies…”); while (true) { InetSocketAddress sa; sa = receivePacket (channel, buffer); buffer.flip(); replies++; printTime (longBuffer.getLong (0), sa); if (replies == expect) { System.out.println (”All packets answered”); break; } 117

Hint: If you are looking for very good and affordable webspace to host and run your tomcat hosting application check Virtualwebstudio tomcat web hosting provider

be silently discarded. Invoking send() sends the content

Tuesday, October 31st, 2006

public abstract long write(ByteBuffer[] srcs) throws IOException; public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException; } The read() method returns the number of bytes read, which may be zero if the channel is in nonblocking mode. The return value of write() is consistent with send(): either the number of bytes in your buffer(s) or 0 if the datagram cannot be sent (because the channel is nonblocking). Either can throw NotYetConnectedException if invoked while the DatagramChannel is not in a connected state. Datagram channels are different beasts than stream sockets. Stream sockets are immensely useful because of their ordered, reliable data-transport characteristics. Most network connections are stream sockets (predominantly TCP/IP). But stream-oriented protocols such as TCP/IP necessarily incur significant overhead to maintain the stream semantics on top of the packet-oriented Internet infrastructure, and the stream metaphor does not apply to all situations. Datagram throughput can be higher than for stream protocols, and datagrams can do some things streams can’t. Here are some reasons to choose datagram sockets over stream sockets: Your application can tolerate lost or out-of-order data. You want to fire and forget and don’t need to know if the packets you sent were received. Throughput is more important than reliability. You need to send to multiple receivers (multicast or broadcast) simultaneously. The packet metaphor fits the task at hand better than the stream metaphor. If one or more of these characteristics apply to your application, then a datagram design may be appropriate. Example 3-9 shows how to use a DatagramChannel to issue requests to time servers at multiple addresses. It then waits for the replies to arrive. For each reply that comes back, the remote time is compared to the local time. Because datagram delivery is not guaranteed, some responses may never arrive. Most Linux and Unix systems provide time service by default. There are also several public time servers on the Internet, such as time.nist.gov. Firewalls or your ISP may interfere with datagram delivery. Your mileage may vary. Example 3-9. Time-service client using DatagramChannel package com.ronsoft.books.nio.channels; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.DatagramChannel; import java.net.InetSocketAddress; import java.util.Date; 115
Note: If you are looking for best hosting provider to host and run your tomcat application check Astra tomcat hosting services

be silently discarded. Invoking send() sends the content

Tuesday, October 31st, 2006

By the same token, when a DatagramChannel is connected, you cannot send to any destination address except the one given to the connect() method. Attempting to do so results in a SecurityException. Connect a DatagramChannel by calling its connect() method with a SocketAddress object describing the address of the remote peer. If a security manager is installed, it’s consulted to check permission. Thereafter, the security check overhead will not be incurred on each send/receive because packets to or from any other address are not allowed. A scenario in which connected channels might be useful is a real-time, client/server game using UDP communication. Any given client will always be talking to the same server and wants to ignore packets from any other source. Placing the client’s DatagramChannel instance in a connected state reduces the per-packet overhead (because security checks are not needed on each packet) and filters out bogus packets from cheating players. The server may want to do the same thing, but doing so requires a DatagramChannel object for each client. Unlike stream sockets, the stateless nature of datagram sockets does not require a dialog with the remote system to set up connection state. There is no actual connection, just local state information that designates the allowed remote address. For this reason, there is no separate finishConnect() method on DatagramChannel. The connected state of a datagram channel can be tested with the isConnected() method. Unlike SocketChannel, which must be connected to be useful and can connect only once, a DatagramChannel object can transition in and out of connected state any number of times. Each connection can be to a different remote address. Invoking disconnect() configures the channel so that it can once again receive from, or send to, any remote address as allowed by the security manager, if one is installed. While a DatagramChannel is connected, it’s not necessary to supply the destination address when sending, and the source address is known when receiving. This means that the conventional read() and write() methods can be used on a DatagramChannel while it’s connected, including the scatter/gather versions to assemble or disassemble packet data: public abstract class DatagramChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { // This is a partial API listing public abstract int read (ByteBuffer dst) throws IOException; public abstract long read (ByteBuffer [] dsts) throws IOException; public abstract long read (ByteBuffer [] dsts, int offset, int length) throws IOException; public abstract int write (ByteBuffer src) throws IOException; 114
Note: If you are looking for best hosting provider to host and run your tomcat application check Astra tomcat hosting services

be silently discarded. Invoking send() sends the content

Tuesday, October 31st, 2006

be silently discarded. Invoking send() sends the content of the given ByteBuffer object, from its current position to its limit, to the destination address and port described by the given SocketAddress object. If the DatagramChannel object is in blocking mode, the invoking thread may sleep until the datagram can be queued for transmission. If the channel is nonblocking, the return value will be either the number of bytes in the byte buffer or 0. Sending datagrams is an all-or-nothing proposition. If the transmit queue does not have sufficient room to hold the entire datagram, then nothing at all is sent. If a security manager is installed, its checkConnect() method will be called on every invocation of send() or receive() to validate the destination address, unless the channel is in a connected state (discussed later in this section). Note that datagram protocols are inherently unreliable; they make no delivery guarantees. A nonzero return value from send() does not indicate that the datagram arrived at its destination, only that it was successfully queued to the local networking layer for transmission. Additionally, transport protocols along the way may fragment the datagram. Ethernet, for example, cannot transport packets larger than about 1,500 bytes. If your datagram is large, it runs the risk of being broken into pieces, multiplying the chances of packet loss in transit. The datagram will be reassembled at the destination, and the receiver won’t see the fragments, but if any fragments fail to arrive in a timely manner, the entire datagram will be discarded. The DatagramChannel has a connect() method: public abstract class DatagramChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { // This is a partial API listing public abstract DatagramChannel connect (SocketAddress remote) throws IOException; public abstract boolean isConnected(); public abstract DatagramChannel disconnect() throws IOException; } The connection semantics of a DatagramChannel are different for datagram sockets than they are for stream sockets. Sometimes it’s desirable to restrict the datagram conversation to two parties. Placing a DatagramChannel into a connected state causes datagrams to be ignored from any source address other than the one to which the channel is “connected.” This can be helpful because the unwanted packets will be dropped by the networking layer, relieving your code of the effort required to receive, check, and discard them. 113
Note: If you are looking for best hosting provider to host and run your tomcat application check Astra tomcat hosting services

public static void main (String [] argv) throws

Tuesday, October 31st, 2006

have a peer DatagramSocket object that can be obtained by calling the socket() method. DatagramChannel objects can act both as server (listener) and client (sender). If you want the newly created channel to listen, it must first be bound to a port or address/port combination. Binding is no different with DatagramChannel than it is for a conventional DatagramSocket; it’s delegated to the API on the peer socket object: DatagramChannel channel = DatagramChannel.open(); DatagramSocket socket = channel.socket(); socket.bind (new InetSocketAddress (portNumber)); DatagramChannels are connectionless. Each datagram is a self-contained entity, with its own destination address and a data payload independent of every other datagram’s. Unlike stream-oriented sockets, a DatagramChannel can send individual datagrams to different destination addresses. Likewise, a DatagramChannel object can receive packets from any address. Each datagram arrives with information about where it came from (the source address). A DatagramChannel that is not bound can still receive packets. When the underlying socket is created, a dynamically generated port number is assigned to it. Binding requests that the channel’s associated port be set to a specific value (which may involve security checks or other validation). Whether the channel is bound or not, any packets sent will contain the DatagramChannel’s source address, which includes the port number. Unbound DatagramChannels can receive packets addressed to their port, usually in response to a packet sent previously by that channel. Bound channels receive packets sent to the well-known port to which they’ve bound themselves. The actual sending or receiving of data is done by the send() and receive() methods: public abstract class DatagramChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { // This is a partial API listing public abstract SocketAddress receive (ByteBuffer dst) throws IOException; public abstract int send (ByteBuffer src, SocketAddress target) } The receive() method copies the data payload of the next incoming datagram into the provided ByteBuffer and returns a SocketAddress object to indicate where it came from. If the channel is in blocking mode, receive() may sleep indefinitely until a packet arrives. If nonblocking, it returns null if no packets are available. If the packet contains more data than will fit in your buffer, any excess will be silently discarded. If the ByteBuffer you provide does not have sufficient remaining space to hold the packet you’re receiving any bytes that don’t fit will 112
Note: If you are looking for cheap and quality provider to host and run your java application check Astra java hosting services

public static void main (String [] argv) throws

Tuesday, October 31st, 2006

may still be in transit. For this reason, it’s rarely a good design choice to have multiple, noncooperating threads share the same side of a stream socket. The connect() and finishConnect() methods are mutually synchronized, and any read or write calls will block while one of these operations is in progress, even in nonblocking mode. Test the connection state with isConnected() if there’s any doubt or if you can’t afford to let a read or write block on a channel in this circumstance. 3.5.4 DatagramChannel The last of the socket channels is DatagramChannel. Like SocketChannel with Socket and ServerSocketChannel with ServerSocket, every DatagramChannel object has an associated DatagramSocket object. The naming pattern doesn’t quite hold here: “DatagramSocketChannel” is a bit unwieldy, so “DatagramChannel” was chosen instead. Just as SocketChannel models connection-oriented stream protocols such as TCP/IP, DatagramChannel models connectionless packet-oriented protocols such as UDP/IP: public abstract class DatagramChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { // This is a partial API listing public static DatagramChannel open() throws IOException public abstract DatagramSocket socket(); public abstract DatagramChannel connect (SocketAddress remote) throws IOException; public abstract boolean isConnected(); public abstract DatagramChannel disconnect() throws IOException; public abstract SocketAddress receive (ByteBuffer dst) throws IOException; public abstract int send (ByteBuffer src, SocketAddress target) public abstract int read (ByteBuffer dst) throws IOException; public abstract long read (ByteBuffer [] dsts) throws IOException; public abstract long read (ByteBuffer [] dsts, int offset, int length) throws IOException; public abstract int write (ByteBuffer src) throws IOException; public abstract long write(ByteBuffer[] srcs) throws IOException; public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException; } The creation pattern is the same for DatagramChannel as for the other socket channels: invoke the static open() method to create a new instance. The new DatagramChannel will 111
Note: If you are looking for cheap and quality provider to host and run your java application check Astra java hosting services

public static void main (String [] argv) throws

Tuesday, October 31st, 2006

public static void main (String [] argv) throws Exception { String host = “localhost”; int port = 80; if (argv.length == 2) { host = argv [0]; port = Integer.parseInt (argv [1]); } InetSocketAddress addr = new InetSocketAddress (host, port); SocketChannel sc = SocketChannel.open(); sc.configureBlocking (false); System.out.println (”initiating connection”); sc.connect (addr); while ( ! sc.finishConnect()) { doSomethingUseful(); } System.out.println (”connection established”); // Do something with the connected socket // The SocketChannel is still nonblocking sc.close(); } private static void doSomethingUseful() { System.out.println (”doing something useless”); } } If an asynchronous-connection attempt fails, the next invocation of finishConnect() throws an appropriate checked exception to indicate the nature of the problem. The channel will then be closed and cannot be connected or used again. The connection-related methods provide ways to poll a channel and determine its status while a connection is in progress. In Chapter 4, we’ll see how to use Selectors to avoid polling and receive notification when an asynchronous connection has been established. Socket channels are thread-safe. Multiple threads do not need to take special steps to protect against concurrent access, but only one read and one write operation will be in progress at any given time. Keep in mind that sockets are stream-oriented, not packet-oriented. They guarantee that the bytes sent will arrive in the same order but make no promises about maintaining groupings. A sender may write 20 bytes to a socket, and the receiver gets only 3 of those bytes when invoking read(). The remaining 17 bytes 110
Note: If you are looking for cheap and quality provider to host and run your java application check Astra java hosting services

Thread.sleep (2000); } else { System.out.println (”Incoming connection

Tuesday, October 31st, 2006

SocketChannel will return its peer Socket object. Calling getChannel() on that Socket returns the original SocketChannel. Although every SocketChannel object creates a peer Socket object, the reverse is not true. Socket objects created directly do not have associated SocketChannel objects, and their getChannel() methods return null. A newly created SocketChannel is open but not connected. Attempting an I/O operation on an unconnected SocketChannel object will throw a NotYetConnectedException. The socket can be connected by calling connect() directly on the channel or by calling the connect() method on the associated Socket object. Once a socket channel is connected, it remains connected until it closes. You can test whether a particular SocketChannel is currently connected by invoking the boolean isConnected() method. The second form of open(), which takes an InetSocketAddress argument, is a convenience method that connects before returning. This: SocketChannel socketChannel = SocketChannel.open (new InetSocketAddress (”somehost”, somePort)); is equivalent to this: SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect (new InetSocketAddress (”somehost”, somePort)); If you choose to make the connection the traditional way by invoking connect() on the peer Socket object the traditional connection semantics apply. The thread will block until the connection is established, or until the supplied timeout expires. If you choose to make the connection by calling connect() directly on the channel, and the channel is in blocking mode (the default), the connection process is effectively the same. There is no version of connect() on SocketChannel that lets you provide a timeout value. Instead, SocketChannel provides concurrent connection when connect() is invoked in nonblocking mode: it initiates a connection to the requested address then returns immediately. If the return value from connect() is true, the connection was established immediately (this may happen for local loopback connections). If the connection cannot be established immediately, connect() will return false, and connection establishment proceeds concurrently. Stream-oriented sockets take time to set up because a packet dialog must take place between the two connecting systems to establish the state information needed to maintain the stream socket. Connecting to remote systems across the open Internet can be especially time-consuming. If a concurrent connection is underway on a SocketChannel, the isConnectPending() method returns true. 108
Note: If you are looking for cheap and inexpensive provider to host and run your tomcat application check Actions tomcat hosting services

Thread.sleep (2000); } else { System.out.println (”Incoming connection

Tuesday, October 31st, 2006

Call finishConnect() to complete the connection process. This method can be called safely at any time. One of the following will happen when invoking finishConnect() on a SocketChannel object in nonblocking mode: The connect() method has not yet been called. A NoConnectionPendingException is thrown. Connection establishment is underway but not yet complete. Nothing happens, and finishConnect() immediately returns false. The SocketChannel has been switched back to blocking mode since calling connect() in nonblocking mode. If necessary, the invoking thread blocks until connection establishment is complete. finishConnect() then returns true. Connection establishment has completed since the initial invocation of connect() or the last call to finishConnect(). Internal state is updated in the SocketChannel object to complete the transition to connected state, and finishConnect() returns true. The SocketChannel object can then be used to transfer data. The connection is already established. Nothing happens, and finishConnect() returns true. While in this intermediate connection-pending state, you should invoke only finishConnect(), isConnectPending(), or isConnected() on the channel. Once connection establishment has been successfully completed, isConnected() returns true. InetSocketAddress addr = new InetSocketAddress (host, port); SocketChannel sc = SocketChannel.open(); sc.configureBlocking (false); sc.connect (addr); while ( ! sc.finishConnect()) { doSomethingElse(); } doSomethingWithChannel (sc); sc.close(); Example 3-8 illustrates runnable code that manages an asynchronous connection. Example 3-8. Concurrent-connection establishment package com.ronsoft.books.nio.channels; import java.nio.channels.SocketChannel; import java.net.InetSocketAddress; /** * Demonstrate asynchronous connection of a SocketChannel. * @author Ron Hitchens (ron@ronsoft.com) */ public class ConnectAsync{ 109
Note: If you are looking for cheap and inexpensive provider to host and run your tomcat application check Actions tomcat hosting services

Thread.sleep (2000); } else { System.out.println (”Incoming connection

Tuesday, October 31st, 2006

Thread.sleep (2000); } else { System.out.println (”Incoming connection from: ” + sc.socket().getRemoteSocketAddress()); buffer.rewind(); sc.write (buffer); sc.close(); } } } } The final method listed previously, validOps(), is used with selectors. Selectors are discussed in detail in Chapter 4, and validOps() is covered in that discussion. 3.5.3 SocketChannel Let’s move on to SocketChannel, which is the most commonly used socket channel class: public abstract class SocketChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { // This is a partial API listing public static SocketChannel open() throws IOException public static SocketChannel open (InetSocketAddress remote) throws IOException public abstract Socket socket(); public abstract boolean connect (SocketAddress remote) throws IOException; public abstract boolean isConnectionPending(); public abstract boolean finishConnect() throws IOException; public abstract boolean isConnected(); public final int validOps() } The Socket and SocketChannel classes encapsulate point-to-point, ordered network connections similar to those provided by the familiar TCP/IP connections we all know and love. A SocketChannel acts as the client, initiating a connection to a listening server. It cannot receive until connected and then only from the address to which the connection was made. (As with ServerSocketChannel, discussion of the validOps() method will be deferred to Chapter 4 when we examine selectors. The common read/write methods are not listed here either; refer to the section Section 3.1.2 for details.) Every SocketChannel object is created in tandem with a peer java.net.Socket object. The static open() method creates a new SocketChannel object. Invoking socket() on the new 107
Note: If you are looking for cheap and inexpensive provider to host and run your tomcat application check Actions tomcat hosting services

public abstract boolean isBlocking(); public abstract Object blockingLock();

Monday, October 30th, 2006

returning a java.net.Socket object. On the other hand, the accept() method of ServerSocketChannel returns objects of type SocketChannel and is capable of operating in nonblocking mode. If a security manager is in place, both methods perform the same security checks. If invoked in nonblocking mode, ServerSocketChannel.accept() will immediately return null if no incoming connections are currently pending. This ability to check for connections without getting stuck is what enables scalability and reduces complexity. Selectability also comes into play. A ServerSocketChannel object can be registered with a Selector instance to enable notification when new connections arrive. Example 3-7 demonstrates how to use a nonblocking accept(). Example 3-7. A nonblocking accept() with ServerSocketChannel package com.ronsoft.books.nio.channels; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.net.InetSocketAddress; /** * Test nonblocking accept() using ServerSocketChannel. * Start this program, then “telnet localhost 1234″ to * connect to it. * * @author Ron Hitchens (ron@ronsoft.com) */ public class ChannelAccept{ public static final String GREETING = “Hello I must be going.rn”; public static void main (String [] argv) throws Exception { int port = 1234; // default if (argv.length > 0) { port = Integer.parseInt (argv [0]); } ByteBuffer buffer = ByteBuffer.wrap (GREETING.getBytes()); ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind (new InetSocketAddress (port)); ssc.configureBlocking (false); while (true) { System.out.println (”Waiting for connections”); SocketChannel sc = ssc.accept(); if (sc == null) { // no connections, snooze a while 106

Hint: This post is supported by Gama web hosting hrvatska services

public abstract boolean isBlocking(); public abstract Object blockingLock();

Monday, October 30th, 2006

public abstract boolean isBlocking(); public abstract Object blockingLock(); } Readiness selection is a mechanism by which a channel can be queried to determine if it’s ready to perform an operation of interest, such as reading or writing. Nonblocking I/O and selectability are intimately linked. That’s why the API methods for managing blocking mode are defined in the SelectableChannel superclass. The remainder of SelectableChannel’s API will be discussed in Chapter 4. Setting or resetting a channel’s blocking mode is easy. Simply call configureBlocking() with true to place it in blocking mode, or false for nonblocking mode. It’s as simple as that. You can determine which mode a socket channel is currently in by invoking isBlocking(): SocketChannel sc = SocketChannel.open(); sc.configureBlocking (false); // nonblocking … if ( ! sc.isBlocking()) { doSomething (cs); } Nonblocking sockets are usually thought of for server-side use because they make it easier to manage many sockets simultaneously. But there can also be benefits to using one or a few sockets in nonblocking mode on the client side. For example, with nonblocking sockets, a GUI application can pay attention to user requests and carry on conversations with one or more servers simultaneously. Nonblocking mode is useful across a broad range of applications. Occasionally, it’s necessary to prevent changes to the blocking mode of a socket channel. The API provides the blockingLock() method, which returns an opaque object reference. The object returned is the one used internally by the channel implementation when it makes changes to the blocking mode. Only the thread holding the lock on this object will be able to change the channel’s blocking mode. (An object lock is obtained by using the synchronized Java keyword. This is different than the lock() method discussed in Section 3.3.) This can be handy to ensure that the blocking mode of a socket doesn’t change during a critical section of code, or to change the mode temporarily without affecting any other threads. Socket socket = null; Object lockObj = serverChannel.blockingLock(); // have a handle to the lock object, but haven’t locked it yet // may block here until lock is acquired synchronize (lockObj) { // This thread now owns the lock; mode can’t be changed boolean prevState = serverChannel.isBlocking(); 104

Hint: This post is supported by Gama web hosting hrvatska services