Hello folks,
For my final project I decided to write an online poker game. Long story short I'm having trouble with a class I wrote to manage java.net.Sockets.

The source for this class is:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Iterator;
import java.util.LinkedList;

public class SocketMgr implements Runnable
{
	/** Stores the host name that socket will connect to. */
	private String hostname;

	/** Stores the host port that socket will connect to. */
	private int port;

	/** Stores the Socket currently being used. */
	private Socket socket;

	/** Stores the socket input stream reader. */
	private BufferedReader incoming;

	/** Stores the socket output stream writer. */
	private PrintWriter outgoing;

	/** Stores the thread used to listen for incoming data. */
	private Thread thread;

	/** Stores the list of SocketListeners to notify whenever an event occurs. */
	private LinkedList<SocketListener> listeners;

	/**
	 * Constructs a new SocketMgr to manage incoming and outgoing data.
	 * 
	 * @param socket the server-side socket gotten via ServerSocket.accept();
	 */
	public SocketMgr(Socket socket)
	{
		this.hostname = socket.getInetAddress().getHostAddress();
		this.port = socket.getPort();
		this.socket = socket;

		try
		{
			incoming = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			outgoing = new PrintWriter(socket.getOutputStream(), true);
		}
		catch (IOException e)
		{
			System.err.println("Could not setup socket I/O readers!");
		}

		thread = new Thread(this);
		listeners = new LinkedList<SocketListener>();
	}

	/**
	 * Constructs a new SocketMgr to manage incoming and outgoing data from and
	 * to the specified host.
	 * 
	 * @param hostname the IP address or host name of the host server
	 * @param port the port of the host server
	 */
	public SocketMgr(String hostname, int port)
	{
		this.hostname = hostname;
		this.port = port;
		socket = null;
		incoming = null;
		outgoing = null;
		thread = new Thread(this);
		listeners = new LinkedList<SocketListener>();
	}

	/**
	 * Adds the specified SocketListener to the list of objects to notify of
	 * socket events.
	 * 
	 * @param sl the SocketListener to add
	 */
	public synchronized void addSocketListener(SocketListener sl)
	{
		listeners.add(sl);
	}

	/**
	 * Opens a new Socket and listens for incoming messages.
	 */
	public synchronized void connect()
	{
		if (!isConnected())
		{
			try
			{
				fireConnecting();
				socket = new Socket(hostname, port);
				incoming = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				outgoing = new PrintWriter(socket.getOutputStream(), true);
				thread.start();
				fireConnected();
			}
			catch (IOException e)
			{
				fireDisconnecting();
				System.err.println("Could not connect socket to host!");
				try
				{
					socket.close();
				}
				catch (Exception e2)
				{
					// do nothing
				}
				socket = null;
				incoming = null;
				outgoing = null;
				System.gc();
				fireDisconnected();
			}
		}
	}

	/**
	 * Closes the socket if its open and performs garbage collection.
	 */
	public synchronized void disconnect()
	{
		if (isConnected())
		{
			try
			{
				fireDisconnecting();
				socket.close();
			}
			catch (IOException e)
			{
				System.err.println("Problem closing socket... recycling it.");
			}
			socket = null;
			incoming = null;
			outgoing = null;
			System.gc();
			fireDisconnected();
		}
	}

	/**
	 * Checks to see if the Socket is currently connected and listening for
	 * messages.
	 * 
	 * @return true if socket is connected and listening for messages
	 */
	public synchronized boolean isConnected()
	{
		return (socket == null) ? false : (socket.isConnected() && !socket.isClosed());
	}

	/**
	 * Removes the specified SocketListener from the list of objects to notify
	 * of socket events.
	 * 
	 * @param sl the SocketListener to remove
	 */
	public synchronized void removeSocketListener(SocketListener sl)
	{
		listeners.remove(sl);
	}

	/**
	 * Listens for messages while the socket is connected.
	 * DO NOT CALL DIRECTLY! Please use the connect() method.
	 */
	public void run()
	{
		while (isConnected())
		{
			try
			{
				String message;
				if ((message = incoming.readLine()) != null)
					fireMessageReceived(message);
			}
			catch (IOException e)
			{
				System.err.println("Problem receiveing network message!");
			}
		}
	}

	/**
	 * Sends a network message via the socket output stream. Message is sent
	 * immediately.
	 */
	public synchronized void send(String message)
	{
		outgoing.println(message);
		//outgoing.flush(); // auto-flushing now, see connect() and SocketMgr(Socket)
		fireMessageSent(message);
	}

	/**
	 * Notifies all SocketListeners when socket is finished connecting.
	 */
	private void fireConnected()
	{
		SocketEvent evt = new SocketEvent(this, SocketEvent.SOCKET_CONNECTED);
		Iterator<SocketListener> itr = listeners.iterator();
		while (itr.hasNext())
			itr.next().socketConnected(evt);
	}

	/**
	 * Notifies all SocketListeners when socket is about to connect.
	 */
	private void fireConnecting()
	{
		SocketEvent evt = new SocketEvent(this, SocketEvent.SOCKET_CONNECTING);
		Iterator<SocketListener> itr = listeners.iterator();
		while (itr.hasNext())
			itr.next().socketConnecting(evt);
	}

	/**
	 * Notifies all SocketListeners when socket is finished disconnecting.
	 */
	private void fireDisconnected()
	{
		SocketEvent evt = new SocketEvent(this, SocketEvent.SOCKET_DISCONNECTED);
		Iterator<SocketListener> itr = listeners.iterator();
		while (itr.hasNext())
			itr.next().socketDisconnected(evt);
	}

	/**
	 * Notifies all SocketListeners when socket is about to disconnect.
	 */
	private void fireDisconnecting()
	{
		SocketEvent evt = new SocketEvent(this, SocketEvent.SOCKET_DISCONNECTING);
		Iterator<SocketListener> itr = listeners.iterator();
		while (itr.hasNext())
			itr.next().socketDisconnecting(evt);
	}

	/**
	 * Notifies all SocketListeners when a network message is received.
	 */
	private void fireMessageReceived(String message)
	{
		SocketEvent evt = new SocketEvent(this, SocketEvent.SOCKET_MESSAGE_RECEIVED);
		Iterator<SocketListener> itr = listeners.iterator();
		while (itr.hasNext())
			itr.next().socketMessageReceived(evt, message);
	}

	/**
	 * Notifies all SocketListeners when a network message is sent.
	 */
	private void fireMessageSent(String message)
	{
		SocketEvent evt = new SocketEvent(this, SocketEvent.SOCKET_MESSAGE_SENT);
		Iterator<SocketListener> itr = listeners.iterator();
		while (itr.hasNext())
			itr.next().socketMessageSent(evt, message);
	}
}

The complete source for testing this can be found at: http://filebeam.com/4ba225ebdfbe9ac54de6866e937eceab

The problem:
The problem I'm experiencing is that it seems like whenever I call the send() method it only executes the second time I call it and the first message I send gets lost somehow. I have worked around this problem by doing a double send of all messages but I want this problem fixed and I'm out of ideas. I even tried dropping synchronized from the send method but it didn't do much. Hopefully one of you more experienced folks can see what I can't seem to. Thanks in advance for any help or ideas you can give!

Recommended Answers

All 2 Replies

The method itself looks alright, and as you say it works some of the time. How does the code calling send() look? The problem might be in there. Or the problem could even be in the inputstream that handles then sent message.

The method itself looks alright, and as you say it works some of the time. How does the code calling send() look? The problem might be in there. Or the problem could even be in the inputstream that handles then sent message.

OH MY GOD I am such a goof. It was a problem with my System.in scanning where I would store the first scanned line into input then I would try to send the next scanned line instead of sending input. Gah, thanks for your time guys, and for your response slimmy!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.