Hi all
I am creating an application using sockets. Upon execution I want the app to immediately listen for a client socket, if it receives one, it accepts it and becomes the server. However, I am also going to provide the user a GUI with an IP and Port field and a Connect button so that if they choose to they can attempt to connect as a client. If the client connect succeeds the server listen dies. I am having trouble getting around the blocking behavior of ServerSocket.accept. I have packaged my entire SocketConnection into a easy to use class that has been tested and works without error. Does anyone have an idea as to how to implement this functionality into my class? Thanks.
import java.net.*; import java.util.NoSuchElementException; import java.io.*; public class SocketConnection implements Runnable { private boolean isHost = false; private Socket socket = null; private StringBuffer toSend = new StringBuffer(""); private StringBuffer toReceive = new StringBuffer(""); private BufferedReader in = null; private PrintWriter out = null; private final String TERMINATE_CODE = "!"; private boolean terminate = false; public boolean isHost() { return isHost; } public boolean isConnected() { return socket.isConnected(); } public boolean isTerminated() { return terminate; } public boolean isClosed() { return socket.isClosed(); } /** * Constructor for a client socket. Connects to the specified socket located at * the IP address provided and starts a new thread to send/receive data. * @param ip - address of the host computer * @param port - TCP port to be used * @throws IOException - Host found but failed to establish connection * @throws UnknownHostException - Specified host could not be found */ public SocketConnection(String ip, int port) throws UnknownHostException, IOException { isHost = false; socket = new Socket(ip, port); Thread t = new Thread(this); t.start(); } /** * Constructor for a server socket. Listens for and connects to a requesting socket * and starts a new thread to send/receive data. * @param port - TCP port to be used * @throws IOException - Failed to establish connection with requesting client */ public SocketConnection(int port) throws IOException { isHost = true; // Blocks until a client socket request is made ServerSocket hostSocket = new ServerSocket(port); socket = hostSocket.accept(); // Start new dedicated thread to handle send/receive data Thread t = new Thread(this); t.start(); } /** * To determine whether there is arriving data to be processed * @return - true if there is incoming socket data */ public boolean hasIncoming() { return (toReceive.length() > 0); } /** * Closes the open socket connection. */ public void closeConnection() { terminate = true; } /** * Gets the incoming data from the socket connection. If the data contains * more than one command, extracts the first command and leaves the rest in the buffer. * @return A string of the incoming data in text format excluding its newline char * @throws NoSuchElementException - when the incoming data buffer is empty */ public String receive() throws NoSuchElementException { synchronized (toReceive) { if (toReceive.length() == 0) { throw new NoSuchElementException("incoming data buffer is empty"); } String rest; int nextEndline = toReceive.indexOf("\n"); String s = toReceive.substring(0, nextEndline); if (nextEndline < toReceive.length() - 1) { rest = toReceive.substring(nextEndline + 1); toReceive.setLength(0); toReceive.append(rest); } else { toReceive.setLength(0); } return s; } } /** * Sends outgoing data via the socket connection. * @param s - String to be sent out via socket connection * @throws IOException - Failed to write data to socket output */ public void send(String s) throws IOException { synchronized (toSend) { toSend.append(s + "\n"); } } @Override /** * The dedicated thread of the SocketConnection object. Loops infinitely, * sending and receiving data from the socket in/out streams. */ public void run() { try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); String s; while(!terminate || (terminate && ((toSend.length() != 0) || in.ready()))) { // Send data if (toSend.length() != 0) { s = toSend.toString(); out.print(s); out.flush(); if (s.contains(TERMINATE_CODE)) { terminate = true; } toSend.setLength(0); } // Receive data if (in.ready()) { s = in.readLine(); if ((s != null) && (s.length() != 0)) { // Check if it is the end of a transmission if (s.contains(TERMINATE_CODE)) { terminate = true; } // Otherwise, receive what text else { appendToReceive(s + "\n"); } } } } in.close(); out.close(); socket.close(); } catch (IOException e) { System.out.println("I/O stream error in socket thread"); System.exit(1); } } /** * Thread safe way to dump socket input stream data into a * StringBuffer outside of the running thread * @param s - input string to append to the StringBuffer */ private void appendToReceive(String s) { synchronized (toReceive) { toReceive.append(s); } } }