Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Synchronization of Sockets & Threads

807605Jul 25 2007 — edited Jul 25 2007
I have this socket server that accepts connections from clients and it then calls a new thread to deal with each client request. I pass the client socket and a data source into the new thread so that the thread will be able to open an input/output stream to the client. The thread reads in the input from the client and currently just sends it right back. The part that gets tricky for me is when I clean up everything by closing the client socket connection after the thread has finished. Everything works fine for simple requests, but sometimes a client will need to send 4 or 5 requests all at the same time which ends up giving me a SocketException: Socket Closed.

The error is always on the following line:
 inStream.read( size, 0, RECORD_LENGTH_BYTES );
I assume that the threads are closing sockets over each other which causes the problem. I've tried putting in synchronized methods and synchronized statements but it doesn't seem to help.

Any advice on this would be greatly appreciated.

Here is the Thread code:
import java.net.*;
import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;

/*
 * 
 */

public class SocketServerThread extends Thread {
    private static Socket socket = null;
    private static Connection conn= null;
    private static OutputStream outStream = null;
    private static DataSource ds = null;
    private static final int RECORD_LENGTH_BYTES = 4;
    private static InputStream inStream = null;
    private static int counter = 0;
    
    
    public SocketServerThread(Socket theSocket, DataSource theDs) {
	super("SocketServerThread");
		
	socket = theSocket;
	ds = theDs;
    }
    
    

    public void run() {
    	String response = "";
    	int index = 0;
        StringBuffer buffer = new StringBuffer();
              
        System.out.println("New Client Requesting...");
        
        //Set up data source connection
        //dataSourceConnection();
        	
                
        try {
        		
        	
        		inStream = socket.getInputStream();
        		outStream = socket.getOutputStream(); 
        	
        		
        	} catch (UnknownHostException e) {
        		System.err.println("Don't know about host.");
        		clean();
        	} catch (IOException e) {
        		System.err.println("Couldn't get I/O for "
        				+ "the connection.");
        		clean();
        	}
        	
        	try
        	{
        		// read acknowledgement
                // read the first 4 bytes - see how long the response message is
                byte[] size = new byte[RECORD_LENGTH_BYTES];
                
                inStream.read( size, 0, RECORD_LENGTH_BYTES );
        	
                for (index = 0; index < RECORD_LENGTH_BYTES; index++)
                {
                    buffer.append((char)size[index]);
                }
                
                // The number of bytes left in the inputstream to read in 
                try
                {
                    int recordLength = (new Integer(buffer.toString()).intValue()) 
                                                           - RECORD_LENGTH_BYTES;
            
                    byte[] msg = new byte[recordLength];
                    inStream.read( msg, 0, recordLength );
            
                    for (index = 0; index < recordLength; index++)
                    {
                        buffer.append((char)msg[index]);
                    }
                }
                
                catch (NumberFormatException nfe)
                {
                    System.out.println("Unless running Connection Pool " 
                        + "/ Factory J-Units, you should NOT see this message");
                    clean();
                }
                
                System.out.println("------------------------- " + ++counter 
                                   + " -------------------------");
                
                System.out.println("*** EbtTestServer Recieved: " 
                                   + buffer.toString());
                
                response = buffer.toString();
                
                outStream.write( response.getBytes() );
                outStream.flush();
        	}catch(IOException e){e.printStackTrace(); clean();}
        	
        clean();
        
        	
    }
        
        
    
    private synchronized static void clean()
    {
    	try{
    		socket.close();
    		inStream.close();
			outStream.close();
			
			//conn.close();
		}catch(IOException e){e.printStackTrace();}
		//catch(SQLException s){s.printStackTrace();}
    }
}
Here is the socket server code:
 import java.net.*;
import java.io.*;
import javax.naming.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Hashtable;

/*
 * 
 */

public class SocketServer {
	 static boolean listening = true;
	 public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
	 private static ServerSocket serverSocket = null;
	 private static DataSource ds = null;
	 
	public void endListening()
	{
		listening = false;
	}
	private static void usage()
    {
            System.err.println("Usage: SocketServer " +      "<hostname> <port number>");
            System.exit(-1);
    }
	
	public static void main(String[] argv) throws IOException 
	{
                        
        // Get hostname and port from arguments
        if (argv.length < 2)
        {
            usage();
        }

        String host = argv[0];
        int port = 0;
        InitialContext ic = null;
        
        //Connection conn = null;
       
        try
        {
            port = Integer.parseInt(argv[1]);
        }
        catch (NumberFormatException nfe)
        {
            usage();
            clean();
        }
       
       // Set up Socket Server on Port
        try {
            serverSocket = new ServerSocket(4444);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 4444.");
            clean();
            System.exit(-1);
        }
        
        //Set up connection to DB
        
        try
        {
            ic = getInitialContext("t3://" + host + ":" + port);
            ds  = (DataSource) ic.lookup("data-source");
           
            
            
        }
        catch (Throwable t)
        {
            t.printStackTrace();
            clean();
            System.exit(-1);
        }
        
        
        System.out.println("Server Running...");
        
       // Wait for connection from client, then create new thread to handle client
       while(listening)
       {
               
    	   new SocketServerThread(serverSocket.accept(), ds).start();
       }
       
       clean();
       		      
       
    }
	
	
	private static InitialContext getInitialContext(String url)
    throws NamingException
    {

        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
        env.put(Context.PROVIDER_URL, url);

        return new InitialContext(env);
    }
	private synchronized static void clean()
	{
		try
		{
			serverSocket.close();
			
		}catch(IOException e){e.printStackTrace();}
	}
	
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Aug 22 2007
Added on Jul 25 2007
7 comments
1,734 views