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!