?
Solved

NIO SocketChannel connect()

Posted on 2003-11-07
10
Medium Priority
?
1,675 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
10 Comments
 
LVL 35

Expert Comment

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

Expert Comment

by:girionis
ID: 9700843
 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
ID: 9700906
>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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 35

Expert Comment

by:girionis
ID: 9701005
 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
ID: 9701093
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
 
LVL 35

Expert Comment

by:girionis
ID: 9701165
 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 2000 total points
ID: 9701183
 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
ID: 9701200
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
ID: 9701262
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
ID: 9701339
 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 does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
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 arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…

718 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