Solved

NIO

Posted on 2003-11-06
12
705 Views
Last Modified: 2013-12-29
I have a Client which initiates the chat session and a Server which distributes the client messages to all the participating clients.   I'm doing this using the java package .nio but have trouble dealing with Socket, SocketChannel, ServerSocket, and ServerSocketChannel and in particular trying to make the connection.   Below is what I have so far, which generates a BindException when run.   Could someone suggest what is it that's causing the error?   Thanks.

// Server side
ServerSocketChannel ssc = ServerSocketChannel.open();
InetSocketAddress address = new InetSocketAddress(port); // port obtained from stad in
ServerSocket ss = ssc.socket();
ss.bind(address);

while (true) { // Keep accepting connections forever
            SocketChannel sc = ssc.accept();

// do data transfer using ByteBuffer here...

// Client side
sc = SocketChannel.open();
InetSocketAddress address = new InetSocketAddress(port); // port obtained from std in
Socket s = sc.socket();
s.connect(address);
----------------------------------
Also, if I want to send a message string from the client to the server, does this seems to be the correct way of doing it using ByteBuffer?

// Client writes into the buffer to the channel
ByteBuffer buffer = ByteBuffer.allocate(50); // default capacity
byte[] barray = new byte[50];
barray = message.getBytes();
for (int i = 0; i < barray.length; i++)
   buffer.put(barray[i]); // puts the message String into the byte buffer
SocketChannel sc;
sc.write(buffer); // sends it to the server
-----------------------------------
0
Comment
Question by:skyblue01
  • 6
  • 4
  • 2
12 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 9697665
Are you sure that there is not *already* a socket running on that port?

I would use a BufferedWriter to send the message.
0
 

Author Comment

by:skyblue01
ID: 9697694
>are you sure that there is not *already* a socket running on that port?

no, because how i get the socket is by:
SocketChannel sc;
Socket s = sc.socket();

I therefore have no existing socket...
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9697728
Well I didn't necessarily mean in Java. Can you post the full stack trace? Also what port are you trying to connect to, on what address?
0
 
LVL 92

Expert Comment

by:objects
ID: 9697787
byte[] barray = message.getBytes();
ByteBuffer buffer = ByteBuffer.allocate(barray.length);
buffer.put(barray);
sc.write(buffer); // sends it to the server
0
 
LVL 92

Expert Comment

by:objects
ID: 9697813
Are you gettng the BindException on the server or client?
If it's on the server then check if the port is already open by say telnetting to it:

telnet <host> <port>

This should fail to connect if the port is not open.

> InetSocketAddress address = new InetSocketAddress(port);

On the client, try specifying the host the client is trying to connect to.
0
 

Author Comment

by:skyblue01
ID: 9698042
How I run the chat system is as follows:
First run the server giving a random port number (e.g. java Server 5000)
Then run the client giving a port number to connect to (e.g. java Client 5000)
Possibly run another client who want to join the session (e.g. java Client 5000)

I'm still getting the same BindExeption: cannot assign requested address: connect...   Since I had no trouble when using Data Input/Output Streams before using NIO, I thought if it's possible to look at what I have and maybe suggest something that I'm doing wrong.  

-------------------Server.java--------------------
import java.awt.*;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;

public class Server {

    private ServerSocketChannel ssc;
    private ServerSocket ss; // the ServerSocket that is used for accepting new connections
    private Hashtable outputChannels = new Hashtable();
    private SocketChannel sc;

    public Server(int port) throws IOException {
        listen(port); // all that is done is to listen
    }

    private void listen(int port) throws IOException {

        ssc = ServerSocketChannel.open();
        InetSocketAddress address = new InetSocketAddress(port);
        ss = ssc.socket();
        ss.bind(address);

        System.out.println("Listening on " + ss); // Tell the world we're ready to go

        while (true) { // Keep accepting connections forever

            sc = ssc.accept(); // SocketChannel sc?

            System.out.println("Connection from " + sc); // Tell the world we've got it

            outputChannels.put(sc, null);

            new ServerThread(this, sc); // Create a new thread for this connection, and then forget about it
        }
    }

    Enumeration getOutputChannels() {
        return outputChannels.elements();
    }

    // sendToAll method sends a message to all clients
    void sendToAll(String message) {

        synchronized(sc) {

            for (Enumeration e = getOutputChannels(); e.hasMoreElements();) { // for each client

                sc = (SocketChannel) e.nextElement(); // gets the output channel -- SocketChannel sc?

                try {
                    byte[] barray = message.getBytes();
                    ByteBuffer buffer = ByteBuffer.allocate(barray.length);
                    buffer.put(barray); // puts the message into the byte buffer
                    sc.write(buffer); // and sends the message
                } catch(IOException ie) { System.out.println(ie); }
            }
        }
    }

    void removeConnection(SocketChannel sc) {

        synchronized(outputChannels) { // synchronized so sendToAll() won't get messed up while it walks down the list of all output channels

            System.out.println("Removing connection to " + sc); // tells the world

            outputChannels.remove(sc); // removes it from our hashtable/list

            try {
                Socket s = sc.socket();
                s.close(); // makes sure it's closed
            } catch(IOException ie) {
                System.out.println("Error closing " + sc);
                ie.printStackTrace();
            }
        }
    }

    ServerSocket getServerSocket() {
        return ss;
    }

    // starts the server
    static public void main(String args[]) throws Exception {
        try {
            final int port = Integer.parseInt(args[0]); // gets the port # from the command line

            Runnable serverRunnable = new Runnable() {
                public void run() {
                    try {
                        Server s = new Server( port ); // creates a Server object, which will automatically begin accepting connections
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };

            Thread serverThread = new Thread(serverRunnable);
            serverThread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
---------------------ServerThread.java-------------------
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;

// a thread created for each connection to the server
public class ServerThread extends Thread {
    private Server server; // the server that spawned the thread
    private SocketChannel socketChannel; // the socket channel connected to the client
    private ByteBuffer buffer;

    public ServerThread(Server server, SocketChannel socketChannel) {
        this.server = server; // saves the server parameter
        this.socketChannel = socketChannel; // saves the socket channel parameter

        start(); // starts up the thread
    }

    public void run() {

        try {
            String message = "";

            while (true) {
                buffer = ByteBuffer.allocate(50);
                buffer.clear();
                socketChannel.read(buffer);

                while (buffer.remaining() > 0) {
                    Byte b = new Byte(buffer.get());
                    message += b.toString();
                }

                System.out.println("Sending " + message); // tells the world

                server.sendToAll(message); // and have the server send it to all clients
            }
        } catch(EOFException ie) {
        } catch(IOException ie) { // this doesn't need an error message

        ie.printStackTrace(); // this does; tells the world
        } finally {
            server.removeConnection( socketChannel ); // the connection is closed for one reason or another, so have the server deal with it
        }
    }
}
--------------------Client.java-----------------------
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import javax.swing.*;

public class Client extends Panel implements Runnable {

    private JLabel jl =  new JLabel();
    private TextField tf = new TextField(); // text field component for the visual display of the chat windows
    private TextArea ta = new TextArea(); // text area component for the visual display of the chat windows

    private Socket s; // the socket connecting to the server
    private SocketChannel sc;
    private ByteBuffer buffer;

    public Client(String host, int port) {

        setLayout(new BorderLayout()); // sets up the screen
        add("North", jl);
        add("South", tf);
        add("Center", ta);

        jl.setText(host);

        tf.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                processMessage(e.getActionCommand()); // receives messages when someone types a line and hits return, using an anonymous class as a callback
            }
        } );

        try {
            sc = SocketChannel.open();
            InetSocketAddress address = new InetSocketAddress(port);
            Socket s = sc.socket();
            s.connect(address);

            System.out.println("connected to " + sc); // gets a connection, tells the world

            new Thread(this).start(); // starts a background thread for receiving messages
        } catch(IOException ie) { System.out.println(ie); }
    }

    private void processMessage(String message) {
        try {
            byte[] barray = message.getBytes();
            buffer = ByteBuffer.allocate(barray.length);
            buffer.put(barray); // puts the message into the byte buffer
            sc.write(buffer); // sends it to the server

            tf.setText(""); // clears out text input field
        } catch(IOException ie) { System.out.println(ie); }
    }

    public void run() {
        //try {
            while (true) {
                String message = "";
                ByteBuffer buffer = ByteBuffer.allocate(50); // default capacity
                while (buffer.remaining() > 0) {
                    Byte b = new Byte(buffer.get()); // gets the next message
                    message += b.toString();
                }

                ta.append(message + "\n"); // prints it to our text window
            }
        //} catch(IOException ie) { System.out.println(ie); }
    }

    // runs the clinet
    static public void main(String args[]) throws Exception {
        try {
            final int port = Integer.parseInt(args[0]); // gets the port # from the command line

            Runnable clientRunnable = new Runnable() {
                public void run() {
                    try {
                        Client c = new Client("local host", port); // creates a Client object, which will automatically begin initiating connections
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };

            Thread clientThread = new Thread(clientRunnable);
            clientThread.start();

            JFrame win = new JFrame();
            win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            win.setSize(512, 512);
            win.setBackground(Color.gray);
            Container c = win.getContentPane();

            c.setLayout(new BorderLayout());
            c.add("Center", new Client("localhost", port));

            win.setVisible(true);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
----------------------------------------------------------
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 92

Expert Comment

by:objects
ID: 9698053
> I'm still getting the same BindExeption: cannot assign requested address: connect...

when exactly do you get this error?
0
 

Author Comment

by:skyblue01
ID: 9698066
When I run the Clinet after I run the Server, I get the BindException.   If the connection is successful and the client message is successfully distrubuted to all the clients, this error should not print in std out.
0
 
LVL 92

Accepted Solution

by:
objects earned 500 total points
ID: 9698075
Did you try my suggestion above to specify the host for the client to connect to?

            sc = SocketChannel.open();
            InetSocketAddress address = new InetSocketAddress(host, port);
            Socket s = sc.socket();
            s.connect(address);

0
 
LVL 92

Expert Comment

by:objects
ID: 9698087
unrelated but you can't add a null value to a Hashtable:

> outputChannels.put(sc, null);
0
 

Author Comment

by:skyblue01
ID: 9698111
Is Hashtable outputChannels necessary to keep track of all different SocketChannels or do you think it's possible to get rid of it?

Also, with your above suggestion I was able to get rid of the BindException thing.   I now got another problem but I'll try working on that and post another question if I get stuck again (it might even be the thing with the hashtable...).   Thanks!
0
 
LVL 92

Expert Comment

by:objects
ID: 9698159
> Is Hashtable outputChannels necessary to keep track of all different
> SocketChannels or do you think it's possible to get rid of it?

No you need something to track all the client connections, but I see no need for it to be a Hashtable. Just a List would seem to suffice on what you have so far.

:-)

http://www.objects.com.au
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now