Please support my sponors and make this site possible!!!
Please support our sponsors!

 

Home > Core Java FAQ > Networking FAQ
Networking
URL Connections(16) * Internet Addresses(14) *  Sockets(23)  * Security(01)  * Miscellaneous (14) 
 
Q . How do I create and use sockets in Java?

Ans : 

Create Socket instances on the client side by specifying a host and port number to connect to, and create ServerSocket instances on the server side by specifying a port number at which to wait for new connections.

     Sockets work in pairs, with a built-in asymmetry between client and server. The Socket class in the java.net package represents a client socket. It is always created with a communication target: a communications port number on a specific host machine. The client socket typically initiates interactions. It sends messages over the net to its target, expecting that the right kind of program will be waiting at the specified port, ready to respond to the client's message.
     The server socket, represented by the ServerSocket class, plays this second, wait-and-respond role. A server socket need only specify a port number to listen at; it doesn't have to know in advance to where it will send messages. For each incoming message, it sends its reply back to the source address indicated in the message. In this way, a single process at a server socket can reply to many different clients on different machines.
     The key to using sockets is to keep in mind that they provide only a low-level abstraction of a communication channel as a stream of bytes. The SocketExample sample code, for instance, shows how to pack a Java String instance into an array of bytes and then write that array to the output stream of the socket. To receive data from the server, a useful strategy is to wrap a DataInputStream instance around the client socket's input stream and then use an appropriate read method for the data type(s) you expect.

Q . How can I get a server socket and client socket going on a stand-alone machine, not on a network?

Ans : 

In the JDK 1.1 (but not 1.0.2, due to a bug), you can use the loopback interface—IP address 127.0.0.1—for socket communication without a network.

     Creating a Socket instance requires that you specify the host to connect to, either by name or as an InetAddress instance. Standard TCP/IP practice reserves a special IP address—127.0.0.1—as the loopback interface. Data packets sent to this address don't actually leave the machine; they are passed by software to the same machine's receiving ports, as if they had come in off the network. Thus, you can use this loopback address to test or run network code, even if your machine is not on a network.
     Using the loopback interface affects code only for the client socket. It must create a Socket instance using "127.0.0.1" as the target address:

     InetAddress loopback = InetAddress.getByName("127.0.0.1");
connection = new Socket(loopback, SERVER_PORT);
No special code is needed for a server socket. As always, it uses whatever address the client socket is connecting from.
     The above code works in the JDK 1.1, but a bug in the JDK 1.0.2 implementation prevents loopback connections from working if your machine isn't on a network. In particular, InetAddress's getByName method in 1.0.2 requires that domain name lookup succeed before it returns an InetAddress instance. This is a bug, not a feature, and it prevents you from creating an InetAddress instance by means of the "127.0.0.1" address.
Q . Will raw sockets ever be introduced—and if not, how can I create ICMP messages so that I can do operations like `ping'?

Ans :  

Raw sockets are not currently scheduled for an upcoming release, and without them, your only option for such low-level network access is to write your own native methods.

     The socket operations provided by the java.net classes deliberately shelter you from the lower layers of the TCP/IP protocol stack. Once you create a socket, you only have to worry about sending and receiving data through it. The nitpicky details of the lower transport layers, such as IP addresses, packet sequence numbers, and packet checksums are managed by system code. For the great majority of applications, this division of labor is desirable.
     For a small set of applications, though, the higher-level abstraction provided by sockets shields the very data—the header bytes in an individual packet—that the application needs to control. The UNIX "ping" program, for instance, manipulates individual packets at the level of IP headers, in order to send packets conforming to the Internet Control Message Protocol (ICMP). You simply can't write a ping program using Java socket-related classes. For network control at this level, you need to write native methods.

Q . How do I detect if an input stream belonging to a socket has been terminated by the remote host?

Ans :

Check the return value of your read (or readLine, etc.) method; if the remote host has terminated the socket input stream from its end, your invocation of read should return an end-of-stream value.

     Like other input streams, a socket's input stream signals the end of its data by returning the standard end-of-stream value, -1, from its read methods. The end of a socket's input stream is determined by the remote host: the remote host marks the end of its data by closing the connection (either the data stream or the whole socket) at its end. On the local side, your program may not detect the closing right away because it may still read in some buffered data first, but your program will eventually detect the end-of-stream mark.
     The base InputStream class returns -1 from its read methods to signal end-of-stream. Because you can build other types of input streams or readers on top of the basic input stream, you need to check for the appropriate end-of-stream marker for the specific type you're using: -1 for read methods that return int and null for readLine methods that return String.
     Note: InputStream's available method cannot detect the closing of an input stream—it merely reports how many bytes can be read from the input stream without blocking. In other words, it basically tells you how many bytes are in the TCP buffer on the local receiving end of the current connection; it does not indicate the state of the remote host.

Q . If the Socket class has no support for firewalls, how can I get my Java program with sockets to work through different firewalls?

Ans :  

Define a SocketImpl subclass that can work through your firewall, and use Socket's setSocketImplFactory method to configure your application with that SocketImpl subclass.

     The Socket class provides a front-end interface for socket operations. It lets you open and close socket connections, obtain input and output streams from the socket, and so on. Although you invoke methods on a Socket object, that object does very little of the work. Instead, it delegates practically all of the implementation details to a separate implementation object, which belongs to a subclass of SocketImpl. The Socket getOutputStream method in the JDK (1.0.2 and 1.1), for example, shows how simple the delegation can be:

     /* in Socket.java (JDK 1.0.2 and 1.1): */
     public OutputStream getOutputStream() throws IOException {
         return impl.getOutputStream();
     }
Building in the back-end know-how for communicating through firewalls requires several steps:
  • define your own SocketImpl subclass; override methods like bind, listen, accept, and connect

  • define a class that implements the SocketImplFactory interface; this interface contains a single method createSocketImpl(), which returns a SocketImpl instance

  • invoke Socket's setSocketImplFactory method, providing your SocketImplFactory object as the argument
     If you don't specify a SocketImplFactory, the JDK (1.0.2 and 1.1) provides an instance of PlainSocketImpl (a nonpublic class in java.net) for you. This implementation class does not conduct security checks and knows how to handle only SOCKS firewalls.
Q . How do I create a nonblocking server socket in Java?


Ans :

You can't, exactly, but you can achieve the same affect by using a separate thread to run ServerSocket's accept method.

     A ServerSocket instance has only one way to wait for incoming connections: by invoking the ServerSocket accept method. The accept method is defined to be a blocking call, which means that the thread invoking it will block further execution until a connection is made. If you want to avoid blocking some central thread in your server code, you should have a separate thread run the accept method. The following code fragment illustrates one approach:

     class ServerThread extends Thread {
         ServerSocket listenSocket;
         Socket acceptSocket;

         /**
          * Creates a new server thread that will listen for a connection
          * at the specified socket.
          */
         public ServerThread(ServerSocket socket) {
             listenSocket = socket;
         }

         /**
          * Accepts a connection and then starts another server thread
          * to wait for the next connection while this thread runs
          * to completion.
          */
         public void run() {
             acceptSocket = listenSocket.accept();
             new ServerThread(listenSocket).start();
             // ... handle current connection
         }
         // ...
     }
Q . Is there a standard Java way to specify the address of the host doing the listening when instantiating a ServerSocket?

Ans :  

In the JDK 1.0.2, you can't specify a local address for a server socket to listen at, but the JDK 1.1 fills this gap by providing an additional ServerSocket constructor taking an InetAddress parameter.

     The JDK 1.0.2 provides two public constructors for the ServerSocket class. When creating a ServerSocket instance, you must specify the port number to listen at for connections, and you can optionally specify a maximum size for the waiting list of connect requests waiting to be accepted:

     ServerSocket(int port)
     ServerSocket(int port, int backlog)
In the JDK 1.0.2, there is no way to specify that the server socket should listen on a specific IP address. This restriction can be an issue on "multihomed" machines, that is, machines with more than one IP address.
     Thanks to strong demand, the JDK 1.1 filled this gap by providing one further constructor in the ServerSocket class:
     ServerSocket(int port, int backlog, InetAddress bindAddr)
The third argument specifies a local IP address for the server socket to listen at. For example, the following (admittedly silly) code fragment defines a server that only allows connections on its loopback interface:
     // ... SERVER_PORT defined elsewhere 
     listenSocket = new ServerSocket(SERVER_PORT, 50,
                        InetAddress.getByName("127.0.0.1"));
The second argument, 50, provides the default value for the request backlog allowed by a server socket. You can set this to another value more appropriate for your program if you wish.
Q . How do I send and/or receive datagram packets?

Ans :  
          

Create an appropriate datagram socket and datagram packet, then send or receive the packet via the socket.

     The java.net package supports two fundamentally different ways to send data over the network: normal sockets and datagram sockets. Normal sockets provide a model of reliable data transport as a stream of bytes (or a matched pair of streams) that connects two network locations. You first establish the connection, and then send (and receive) data through it. The socket implementation hides from you all the gory details of splitting the stream into addressed data packets, ensuring that the packets all arrive at their destination, and reassembling the stream in correct order from the packets. The protocol underlying this model is the Transmission Control Protocol (TCP).
     Datagram sockets, in contrast, provide a more rudimentary, lightweight service for sending out or receiving individual data packets. There is no ongoing connection or data stream, and the delivery mechanism specifically does not guarantee that the data reaches its destination. Instead, for each packet, you have to manage the details of providing a data buffer and appropriate destination address and port number. The protocol underlying this model is the User Datagram Protocol (UDP).
     Using datagrams thus centers around packets: either composing and sending them, or receiving and unpacking them. To send a packet, the standard steps are:

  1. Create a DatagramSocket instance.
  2. Allocate and fill a data buffer (a byte array).
  3. Create a DatagramPacket instance that combines the data buffer with address information.
  4. Send the packet through the socket.
The following code fragment exemplifies these steps:
     InetAddress destination = ...;
     int destinationPort = ...;
     byte[] dataBuffer = ...;
     DatagramSocket socket;
     DatagramPacket packet;
     try {
         socket = new DatagramSocket();
         packet = new DatagramPacket(dataBuffer, dataBuffer.length,
                                     destination, destinationPort);
         socket.send(packet);
         socket.close();
     } catch (Exception e) {
         // ... handle exception
     }
Notice that the DatagramSocket instance created for sending does not require that you specify a port number, since the DatagramPacket instance itself conveys all the necessary routing information. The socket still uses a port number, but it takes one that the system assigns automatically. Another noteworthy point is that the try-catch statement is needed because several of the DatagramSocket methods and constructors throw exceptions.
     Receiving a packet involves many of the same components as sending, except you are preparing an empty packet to be filled:
  1. Create a datagram socket.
  2. Allocate a data buffer, but don't fill it.
  3. Create a datagram packet with that buffer, but with no address information.
  4. Invoke receive on the socket to wait for data to arrive and fill the packet.

The following sample code illustrates each of these steps:

     int MAX_BYTES = 576;
     int SERVER_PORT = ...
     DatagramSocket socket;
     DatagramPacket packet;
     byte[] dataBuffer = new byte[MAX_BYTES];
     try {
         socket = new DatagramSocket(SERVER_PORT);
         packet = new DatagramPacket(dataBuffer, dataBuffer.length);
         socket.receive(packet);
         socket.close();
     } catch (Exception e) {
         // ... handle exception
     }
     // ... process contents of packet
     Datagram sockets distinguish most strongly between the sender and the receiver, but they also distinguish weakly between client and server:
  • A client must know the server's address and port in advance, in order to make the initial contact.
  • A server can read the client's address and port from the datagram packet it receives.
Q . When will I be able to create a broadcast datagram packet?

Ans : 

Starting with the JDK 1.1, you can create broadcast datagram packets.

     Creating a broadcast datagram packet is like creating other datagram packets for sending, except that you use the reserved broadcast address 255.255.255.255. The following code fragment illustrates how:

     InetAddress destination;
     int destinationPort = ...
     DatagramSocket socket;
     DatagramPacket packet;
     byte[] dataBuffer = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 };
     try {
         destination = InetAddress.getByName("255.255.255.255");
         socket = new DatagramSocket();
         packet = new DatagramPacket(dataBuffer, dataBuffer.length,
                                     destination, destinationPort);
         socket.send(packet);
         socket.close();
     } catch (Exception e) { /* ... */ }
     The reason this doesn't work in pre-1.1 JDK releases is that they contain a bug in their getByName method that prevents broadcast packets from working. Looking up an IP address that lacked a Domain Name Service (DNS) entry generates an UnknownHostException, even in cases (like the broadcast address) where the IP address has a useful, well-established meaning independent of DNS.
Q . How do I "timeout" a socket read, as the "select" function in Unix does?

Ans : There are two timeouts at issue here. Use the ServerSocket.setSoTimeout(int millis) for timing out your 'accept()' calls.

For a select() like mechanism, you can poll InputStreams of your connections for available() > 0

URLConnection doesn't have a method for this, but you can do it by using multiple threads. Create a timer thread that would just track time and close the connection after your specified timeout period.
Check the URLConnection to see if it's got any data flowing through it (calling URLConnection.connected() is probably a sufficient test). The URLConnection should be in a separate thread.

Q . Why, when I make a call to DatagramPacket.getlength() does it returns the wrong size?

Ans : 

You are probably reusing a Datagram packet, and it has no way to grow its buffer if a longer packet comes in. Take care of it by calling setLength(max) before reuse.

Failing to do this is a very common mistake.

Q . My socket code looks good, but is broken!

Ans :   

When using sockets you typically open both inward and outward streams. A TCP connection is full duplex, but either the send or receive side may be closed independently. By default, the remote end
will take the close as indicating that the connection has simply been closed, and will close its end as well. Check whether this is happening for you, by adding the matched pair. Use tcpdump to check this.

Q . How do I control the amount of time a socket will linger before resetting?

Ans : 

When a socket wishes to terminate a connection it can "linger", allowing unsent data to be transmitted, or it can "reset" which means that all unsent data will be lost. You can explicitly set a delay before a reset is sent, giving more time for data to be read, or you can specify a delay of zero, meaning a reset will be sent as the java.net.Socket.close() method is invoked.

The socket option SO_LINGER controls whether a connection will be aborted, and if so, the linger delay. Use the java.net.Socket.setSoLinger method, which accepts as parameters a boolean and an int. The boolean flag will activate/deactivate the SO_LINGER option, and the int will control the delay time.

Q . What does the java.net.Socket.setTcpNoDelay method do, and what is Nagle's algorithm?

Ans : 

This method controls the socket option TCP_NODELAY, which allows applications to enable or disable Nagle's algorithm. Nagle's algorithm (described in RFC 896), conserves bandwidth by minimizing the number of segments that are sent. When applications wish to decrease network latency and increase performance, they can disable Nagle's algorithm. Data will be sent earlier, at the cost of an increase in bandwidth consumption.

Q . Why can't my applet connect via sockets, or bind to a local port?

Ans  : 

Applets are subject to heavy security constraints when executing under the control of a browser. Applets are unable to access the local file-system, to bind to local ports, or to connect to a computer via sockets other than the computer from which the applet is loaded. While it may seem to be an annoyance for developers, there are many good reasons why such tight constraints are placed on applets. Applets could bind to well known ports, and service network clients without authorization or consent. Applets executing within firewalls could obtain privileged information, and then send it across the network. Applets could even be infected by viruses, such as the Java StrangeBrew strain. Applets might become infected without an applet author's knowledge and then send information back that might leave hosts vulnerable to attack.

Q . What are socket options, and why should I use them?

Ans : 

Socket options give developers greater control over how sockets behave. Most socket behavior is controlled by the operating system, not Java itself, but as of JDK1.1, you can control several socket options, including SO_TIMEOUT, SO_LINGER, TCP_NODELAY, SO_RCVBUF and SO_SNDBUF.

These are advanced options, and many programmers may want to ignore them. That's OK, but be aware of their existence for the future. You might like to specify a timeout for read operations, to control the amount of time a connection will linger for before a reset is sent, whether Nagle's algorithm is enabled/disabled, or the send and receive buffers for datagram sockets.

Q . When my client connects to my server, why does no data come out?

Ans :   

This is a common problem, made more difficult by the fact that the fault may lie in either the client, or the server, or both. The first step is to try and isolate the cause of the problem, by checking whether the server is responding correctly.

If you're writing a TCP service, then you can telnet to the port the server uses, and check to see if it is responding to data. If so, then the fault is more than likely in the client, and if not, you've found your problem. A debugger can be very helpful in tracking down the precise location of server errors. You could try jdb, which comes with JDK, or use an IDE's debugger like Visual J++ or Borland JBuilder.

If your fault looks like it is in the client, then it can often be caused by buffered I/O. If you're using a buffered stream, or a writer (such as PrintWriter), you may need to manually flush the data. Otherwise, it will be queued up but not sent, causing both client and server to stall. The problem can even be intermittent, as the buffer will flush sometimes (when it becomes full) but not other times.

Q . How can I find out who is accessing my server?

Ans : 

If you're using a DatagramSocket, every packet that you receive will contain 
the address and port from which it was sent.

   DatagramPacket packet = null;

   // Receive next packet
   myDatagramSocket.receive ( packet );

   // Print address + port
   System.out.println ("Packet from : " + 
        packet.getAddress().getHostAddress() + ':' + packet.getPort());

If you're using a ServerSocket, then every socket connection you accept will 
contain similar information. The Socket class has a getInetAddress() and 
getPort() method which will allow you to find the same information.

   Socket mySock = myServerSocket.accept();

   // Print address + port
   System.out.println ("Connection from : " + 
	mySock.getInetAddress().getHostAddress() + ':' + mySock.getPort());
Q . Should I use ServerSocket or DatagramSocket in my applications?

Ans : 

DatagramSocket allows a server to accept UDP packets, whereas ServerSocket allows
an application to accept TCP connections. It depends on the protocol you're trying 
to implement. If you're creating a new protocol, here's a few tips 

DatagramSockets communciate using UDP packets. These packets don't guarantee delivery
- you'll need to handle missing packets in your client/server

ServerSockets communicate using TCP connections. TCP guarantees delivery, 
so all you need to do is have your applications read and write using a socket's 
InputStream and OutputStream. 

Q . Can Java sockets talk to C/C++/Perl/Foo sockets?

Ans : 

Yes. Java sockets use the IP protocols TCP and UDP. These are standard internet sockets, and will work with any sockets that also use TCP and UDP. You've just discovered why people get so excited talking about "open systems". I recommend that you pick up Stevens' book (in the bibliography) for an in depth look at how they work. 

Q . I get a SocketException of "Permission Denied" when I try to open up a ServerSocket. What's wrong?

Ans :  

More than likely, you are running under Unix, and trying to open a server socket with a port number <1024. Try a port number >1024, or run your server as root.

Q . I get crashes when I use too many sockets. What's wrong?

Ans :  

This is a bug in Windows 95. Resources are not properly reclaimed when a socket is closed. See the microsoft web site for a patch. (http://www.microsoft.com/) 

Q . Can't I use an IP address to create a socket?

Ans :  

Under JDK 1.0.2, this only works on some machines. This is one of those annoying platform differences that can apparently be traced back to the basic networking libraries on each machine. This is fixed in the 1.1 release. See http://www.cdt.luth.se/~peppar/java/InetAddress/ for one solution to this. 

The example code we are discussing is:
        Socket sock = new Socket("155.152.5.1", 23);

On Solaris and Windows NT, the IP address does not work for IP addresses that do not have associated hostnames. On Linux and Windows 95, the IP address is OK. [Note: Here I am merely repeating things that I've read on USENET. Independent confirmation of this would be appreciated.] 

This is apparently related with problems in the InetAddress class. When InetAddress is instantiated with an IP address, a reverse DNS lookup is done. If the IP address is not associated with a valid hostname, the instantiation will fail. This is part of anti-spoofing, and is relaxed in Java 1.1. In the new version, the reverse lookup will not occur until the hostname is asked for. In Java 1.1,      

InetAddress in = InetAddress.getByName("155.152.5.1");

should always work. 

Copyright © 2000 javafaq.com. All rights reserved