Server socket programming and thread

hello,

briefly this is what i have sought out to do : the server waits for the client indefinitely,upon a client requesting for service by writing a service id into the socket, a new thread of the type id as read by the server which is a sub-class of the Server (main-class) is exec'd.

the problem as i understand is that the client can send as much of data as it desires to the server and the thread can read the data it receives by the clients.the server(thread) fails to write reply to the client;eventhough out.write() is successful;the client is blocked in read() indefinitely.is it because of the thread which runs at a different port the client does not know and the server is not redirecting response to the client.

how do i read what the server(thread) writes onto the socket from the clients.

[830 byte] By [varun_tayura] at [2007-11-26 18:44:29]
# 1

> how do i read what the server(thread) writes onto the socket from the clients

If they are text data, use PrintWriter.println() with auto-flush and BuferedReader.readLine(). You shoul do null-check for every return value from readLine(). You also should do catching EOFException from the read.

hiwaa at 2007-7-9 6:18:23 > top of Java-index,Core,Core APIs...
# 2

thanks but...

the problem is not with the choice between buffereader or the printwriter ,i am not able to read anything the server writes out to the client;

picture this: step 1.server is waiting at port 50001

step2: client connects;writes a request id say 1

step 3:depending on request id i will thread the server instance to do a particular job.if the job requires writing to the client then data apperas on the stream but i am not able to read it.

i.e because after accept() call the original socket into which the client wrote is no longer valid and it is assigned a local port say 1044 and not 50001;so client still is expecting to read 50001 and java's redirection local->remote is too slow which hangs my GUI at client

hope this clears my point.

thanks

varun_tayura at 2007-7-9 6:18:23 > top of Java-index,Core,Core APIs...
# 3

> after accept() call the original socket into which the client wrote is no longer

> valid and it is assigned a local port say 1044 and not 50001

You are wrong.

If you are doing your socket communication within a GUI event handler, you should run the communication part, i.e. I/O part as a separate thread. See http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html

I also suspect, from your weird description about port, that your code that dispatches client handling in the server might be somewhat wrong. Try and study the code below which is a common and standard form of Java client-server application.

/* server */

import java.net.*;

import java.io.*;

public class MiniServer{

ServerSocket ss;

int port = 5555;

public MiniServer(){

try{

ss = new ServerSocket(port);

}

catch (IOException e){

e.printStackTrace();

}

}

public void getConnections(){

while (true){

try{

Socket s = ss.accept();

new Thread(new ConnectionHandler(s)).start();

}

catch (Exception e){

e.printStackTrace();

}

}

}

public static void main(String[] args){

MiniServer ms = new MiniServer();

ms.getConnections();

}

}

class ConnectionHandler implements Runnable{

Socket socket;

PrintWriter pw;

BufferedReader br;

public ConnectionHandler(Socket s){

socket = s;

try{

pw = new PrintWriter(s.getOutputStream(), true);

br = new BufferedReader(new InputStreamReader(s.getInputStream()));

}

catch (Exception e){

e.printStackTrace();

}

}

public void run(){

String str = null;

while(true){

try{

if ((str = br.readLine()) != null){

pw.println("*from server: " + str);

}

}

catch (Exception e){

e.printStackTrace();

}

}

}

}

--

/* client */

import java.net.*;

import java.io.*;

public class MiniClient{

static String rhost = "127.0.0.1";

static int port = 5555;

public static void main(String[] args){

String line = null;

String rep = null;

try{

Socket s = new Socket(rhost, port);

PrintWriter pw = new PrintWriter(s.getOutputStream(), true);

BufferedReader br = new BufferedReader

(new InputStreamReader(s.getInputStream()));

BufferedReader con = new BufferedReader(new InputStreamReader(System.in));

while (true){

line = con.readLine();

if (line.length() > 0){

pw.println(line);

rep = br.readLine();

if (rep != null){

System.out.println(rep);

}

}

}

}

catch (Exception e){

e.printStackTrace();

}

}

}

hiwaa at 2007-7-9 6:18:23 > top of Java-index,Core,Core APIs...
# 4

thanks again,just check out this code please

public class Server extends Thread //create a multi-threaded server

{

/* *Creates a new instance of Server */

StringserverAddr=CodeServer.ServerRun.SERVER_IP_ADDR;

intserverPortNum=CodeServer.ServerRun.SERVER_TCP_PORT;

ServerSocket sSock;

SocketcSocket;

intrequestID=0;

boolean debug=true;

InputStream in =null;

OutputStream out=null;

Server ()

{

}

Server (Socket csocket)

{

this.cSocket = csocket;

}

/* start the server at specifed portNum */

private void initialise ()

{

try

{

//start the server at serverPortNum

sSock=new ServerSocket (serverPortNum);

}

catch (IOException ex)

{

ex.printStackTrace ();

}

/* console output of status of server */

if(debug==true)

System.out.println ("Server waiting @ "+sSock);

}

private void acceptRequest ()

{

try

{

this.cSocket=sSock.accept ();

if(debug==true)

System.out.println ("client socket @ "+cSocket);

}

catch (IOException ex)

{

ex.printStackTrace ();

}

}

private void readRequestID ()

{

/*step 1: determine the type of server before threading

*a request the the type of server got by the request ID

* number */

try

{

in=cSocket.getInputStream ();

requestID =in.read ();

out=cSocket.getOutputStream ();

if(debug==true)

System.out.println ("accross the client:"+requestID);

}

catch (IOException ex)

{

ex.printStackTrace ();

}

}

private void execThreadForRequest ()

{

/*step 2: after requestID is received on the socket.

*its time to decide the server to thread the control into.

*/

switch(requestID)

{

case 1: //invoke the RegisterServer thread

new CodeServer.Core.RegistrationServer (this.cSocket).start ();

break;

case 2: //invoke the ListingServer thread

break;

case 3: //invoke the MessageTransferServer thread

break;

case 4: //invoke the CallSetupServer thread

break;

case 5: //invoke the DisconnectServer thread

break;

case 6: //invoke the ChangeUserStatusServer thread

break;

}

}

public void run ()

{

// client processing code here==super class does nothing here

}

public static void main (String args[]) throws Exception

{

Server s=new Server ();

s.initialise ();

/* start indefinitely the main server thread */

while (true)

{

/* accept() blocks the server for a request

a new request is put into a thread for processing */

s.acceptRequest (); //initialise the clientSocket

s.readRequestID (); //get the actual requested service

s.execThreadForRequest (); //start the actual server thread

}

}

}

/**registration service class;

*registers the IP address of the caller,callee and the status

*adds the caller to the hash table and updates status

*/

class RegistrationServer extends Server

{

Socket cSocket;

InetAddress clientAddr;

DataInputStreaminStream;

DataOutputStreamoutStream;

//Socket s=new Socket()

RegistrationServer (Socket cSocket)

{

this.cSocket=cSocket;

clientAddr =cSocket.getInetAddress ();

try

{

//init for reading status and custom message.

inStream=new DataInputStream (cSocket.getInputStream ());

outStream=new DataOutputStream (cSocket.getOutputStream ());

}

catch (IOException ex)

{

ex.printStackTrace ();

}

if(CodeServer.ROO.DEBUG==true)

System.out.println ("register server:"+cSocket

+" host ip:"+clientAddr.getHostName ());

}

public void run ()

{

intstatus=0;

String custMesg=null;

try

{

/* read the custom message */

if(inStream.available ()>0)

{

try

{

custMesg=inStream.readUTF ();

System.out.println (""+custMesg);

}

catch(EOFException e)

{

e.printStackTrace ();

}

}

else

{

custMesg="";

}

}

catch (IOException ex)

{

ex.printStackTrace ();

}

try

{

/* **************************************

here is the problem, i found if i try reading accross the client

i only receive a junk value 81 always */

outStream.write(1); //write success

outStream.flush();

}

catch (IOException ex)

{

ex.printStackTrace ();

}

}

}

}

and with the client GUI :thanks for the help.please do find time to help me out with a suggestion or two on this code.

varun_tayura at 2007-7-9 6:18:23 > top of Java-index,Core,Core APIs...
# 5

> public class Server extends Thread

Weird. Server is a single executing entity. It does not need to be a separate thread.

> public void run ()

> {

> // client processing code here==super class does nothing here

> }

Write this in a ClientHandler class that should implements Runnable, from which you make each client-handling thread and start() it from within the Server. Do the whole client-server I/0 in this run method or methods called from it.

See the simple prototype in my previous reply.

> public static void main (String args[]) throws Exception

Your current main() method is a mess because of the above weirdness.

> here is the problem, i found if i try reading accross the client

> i only receive a junk value 81 always */

> outStream.write(1); //write success

Your client code is also wrong and has bug.

And for DataOutputStream, you should use specific writeXxx() method wher Xxx is some specific type name like 'int' -- then client should use DataInputStream.readXxx() method for reading. In your current code, this proper pairing rule must be violated.

hiwaa at 2007-7-9 6:18:24 > top of Java-index,Core,Core APIs...
# 6
thanks a ton for those corrections ;i will get back shortly.and your pet on the homepage is cute.
varun_tayura at 2007-7-9 6:18:24 > top of Java-index,Core,Core APIs...