Solved

NIO SocketChannel connect()

Posted on 2003-11-07
10
1,580 Views
Last Modified: 2013-12-29
This is part of the simple chat program where the client sends a message to the server which the server redirects it back to all the connected clients.   In particular, I'm having problem with the clinet not getting connected to the server after invoking the connect() method.   I have tested in my code, to see if the connection is finished by socketChannel.finishConnect() but generates an error saying that I'm getting a NoConnectionPendingException which basically telling me that the connect() method has not yet been called.   Since connect() is called inside my Client constructor, I want to know why this is happening.   Below is what I have for the Client class.   Any suggestion will be greatly appreciated.   Thanks.

------------Client class-------------------
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 TextArea ta = new TextArea(); // text area component for the visual display of the chat windows
    private TextField tf = new TextField(); // text field component for the visual display of the chat windows

    private Socket s; // the socket connecting to the server
    private SocketChannel sc;
    private ByteBuffer buffer = ByteBuffer.allocate(50); // default capacity

    public Client(String host, int port) {

        System.out.println("Testing... Client()"); // TEST

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

        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(host, port);
            Socket s = sc.socket();
            s.connect(address); //<---------------------------------------connect() invoked HERE!!

            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 {
            System.out.println("Testing... Client.run()"); // TEST

            while (true) {
                String message = "\n";
                buffer.clear();

                try {
                    while (!sc.finishConnect()) // TEST<----------------finishConnect() called for test!!
                        Thread.sleep(2000);
                } catch (InterruptedException ie) { System.out.println(ie); }

                sc.read(buffer); // try not to use sc here because its used in the constructor

                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); }
    }

    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
Comment
Question by:skyblue01
  • 6
  • 4
10 Comments
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 You do not need both Socket and ChannelSocket. Just use one.
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 Take a look here for sample client and server code:

http://developer.java.sun.com/developer/technicalArticles/releases/nio/

  Also I think 350 points are moer thna enough for this question. 100 would be enough :)
0
 

Author Comment

by:skyblue01
Comment Utility
>Also I think 350 points are moer thna enough for this question. 100 would be enough
This is kind of urgent so...

I tried getting rid of Socket and invoking connect() with SocketChannel, as which I tried before, but it generates another error, UnresolvedAddressException at where I call connect().   I changed it back to Socket because I didn't know what the problem was...   When I use InetAddress, I specify the host and the port number.   Is this where the problem is caused?   I directly use the port I obtain from the user input and for the host, I just set to "localhost".   I've also looked at couple sample codes but it seems to me that I'm doing right...   Is this kind of problem very common?
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 Change this:

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

  to this:

InetSocketAddress address =
        new InetSocketAddress(host, port);
      // Connect
      sc = SocketChannel.open();
      sc.configureBlocking(false);
      sc.connect(address);

 and try again. Make sure *there is* a server running on the specified host and port.
0
 

Author Comment

by:skyblue01
Comment Utility
Yeah I still get the UnresolvedAddress thing...   I can post what I'm doing with the other two classes Server and ServerThread if that helps.   Though there might be problems in other classes too, I still think what's causing the problem is in the Client class.  
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 35

Expert Comment

by:girionis
Comment Utility
 You can post your code so I can try to compile and run it but this will probablybe sometime in the week end as I do not currently have jdk1.4.

0
 
LVL 35

Accepted Solution

by:
girionis earned 500 total points
Comment Utility
 For some reason it can't resolve the name.. Try a last thing:

InetSocketAddress address =
    new InetSocketAddress(InetAddress
getByName("localhost"), port);
0
 

Author Comment

by:skyblue01
Comment Utility
Thanks.   Even if you can't compile, if you can try looking through it, I'd be greatly appreciated.   Thanks.  
----------------Server class-------------------
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 LinkedList outputChannels = new LinkedList();
    private SocketChannel sc;
    private ByteBuffer buffer = ByteBuffer.allocate(50); // default capacity

    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.add(sc);

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

    ListIterator getOutputChannels() {
        return outputChannels.listIterator(0);
    }

    void sendToAll(String message) {

        synchronized(sc) {

            for (ListIterator l = getOutputChannels(); l.hasNext();) { // for each client

                SocketChannel scBack = (SocketChannel) l.next(); // gets the output channel -- SocketChannel sc?

                try {
                    byte[] barray = message.getBytes();
                    buffer = ByteBuffer.allocate(barray.length);
                    buffer.put(barray); // puts the message into the byte buffer
                    scBack.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;
    }

    ByteBuffer getByteBuffer() {
        return buffer;
    }

    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 class------------------
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;

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 = "\n";

            while (true) {
                buffer = server.getByteBuffer();
                //buffer.clear();
                socketChannel.read(buffer);

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

                //buffer.flip();

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

                server.sendToAll(message); // and have the server send it to all clients

                buffer.clear();
            }
        } 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
        }
    }
}
-----------------------------------------
0
 

Author Comment

by:skyblue01
Comment Utility
girionis,

The connection state is pending and I don't know why but the address problem went away.   Thanks!!   I still got other bugs to work on but I greatly appreciate for your suggestions!
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 So was it the InetAddress
getByName("localhost") line that worked?

  Thanks for the points btw, glad at least the conenciton problem is gone. If you are stuck again post the new version of your code and I will try to look into it during the weekend :)
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
The viewer will learn how to implement Singleton Design Pattern in Java.
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

744 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

16 Experts available now in Live!

Get 1:1 Help Now