NIO

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
-----------------------------------
skyblue01Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
Are you sure that there is not *already* a socket running on that port?

I would use a BufferedWriter to send the message.
0
skyblue01Author Commented:
>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
CEHJCommented:
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
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

objectsCommented:
byte[] barray = message.getBytes();
ByteBuffer buffer = ByteBuffer.allocate(barray.length);
buffer.put(barray);
sc.write(buffer); // sends it to the server
0
objectsCommented:
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
skyblue01Author Commented:
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
objectsCommented:
> I'm still getting the same BindExeption: cannot assign requested address: connect...

when exactly do you get this error?
0
skyblue01Author Commented:
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
objectsCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
objectsCommented:
unrelated but you can't add a null value to a Hashtable:

> outputChannels.put(sc, null);
0
skyblue01Author Commented:
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
objectsCommented:
> 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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.