Biscuit128
Biscuit128

Reputation: 5408

Socket Issue - Only first message read

I am very new to sockets and was hoping someone could help me. I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works. The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept(); even though im pretty sure the sender is still sending messages

Can anyone see what i might be doing wrong here please?

Thanks

  public class Sender {
        Socket server = null;
        DataInputStream inp = null;
        PrintStream outp = null;

        public Sender(){
            server = new Socket("127.0.0.1" , 3456);
            outp = new PrintStream(server.getOutputStream());
        }

        private void connectAndSendToServer(String message)  {
            outp = new PrintStream(server.getOutputStream());
            outp.print(message + "\n");
            outp.flush();

        }
    }

Receiver class

public class Receive{


    public String receiveMessage(int port) {
        String message= null;
        ServerSocket listener = null;
        Socket client = null;
        try{
            listener = new ServerSocket(port);
            client = listener.accept();         
            BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
            return br.readLine();

        }
        ...
        finally{
            try {
                if(client!=null && listener!=null){
                    client.close();
                    listener.close();
                }
            } 
            catch (IOException e) {

            }
        }
        return message;
    }
}

Upvotes: 1

Views: 2613

Answers (3)

Kumar Vivek Mitra
Kumar Vivek Mitra

Reputation: 33544

Try this basic Chatting Server written by me. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {

    // ///----------------------------------------Instance Variable Fields
    ServerSocket ss = null;
    Socket incoming = null;

    // ///----------------------------------------Instance Variable Fields

    // ///---------------------------------------- static Variable Fields
    public static ArrayList<Socket> socList = new ArrayList<Socket>();

    // ///---------------------------------------- static Variable Fields

    public void go() {

        try {

            ss = new ServerSocket(25005);

            while (true) {

                incoming = ss.accept();
                socList.add(incoming);
                System.out.println("Incoming: " + incoming);
                new Thread(new ClientHandleKaro(incoming)).start();

            }

        } catch (IOException e) {

            e.printStackTrace();
        } finally {

            try {
                ss.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    class ClientHandleKaro implements Runnable {

        InputStream is = null;
        OutputStream os = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        PrintWriter pw = null;
        boolean isDone = false;

        Socket sInThread = null;

        public ClientHandleKaro(Socket sxxx) {

            this.sInThread = sxxx;

        }

        @Override
        public void run() {

            if (sInThread.isConnected()) {

                System.out.println("Welcamu Clienta");
                System.out.println(socList);
            }

            try {
                is = sInThread.getInputStream();
                System.out.println("IS: " + is);
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);

                os = sInThread.getOutputStream();
                pw = new PrintWriter(os, true);

                String s = new String();

                while ((!isDone) && (s = br.readLine()) != null) {

                    String[] asx = s.split("-");
                    System.out.println("On Console: " + s);

                    // pw.println(s);

                    Thread tx = new Thread(new ReplyKaroToClient(s,
                            this.sInThread));
                    tx.start();

                    if (asx[1].trim().equalsIgnoreCase("BYE")) {

                        System.out.println("I am inside Bye");
                        isDone = true;

                    }
                }
            } catch (IOException e) {

                System.out.println("Thanks for Chatting.....");
            } finally {

                try {
                    Thread tiku = new Thread(new ByeByeKarDo(sInThread));
                    tiku.start();
                    try {
                        tiku.join();
                    } catch (InterruptedException e) {

                        e.printStackTrace();
                    }

                    System.out.println("Accha to hum Chalte hain !!!");
                    System.out.println(socList);

                    br.close();
                    pw.close();
                    sInThread.close();

                } catch (IOException e) {

                }
            }

        }

    }

    class ReplyKaroToClient implements Runnable {

        public String mString;
        public Socket mSocket;

        public ReplyKaroToClient(String s, Socket sIn) {

            this.mString = s;
            this.mSocket = sIn;
        }

        @Override
        public void run() {

            for (Socket sRaW : socList) {

                if (mSocket.equals(sRaW)) {
                    System.out.println("Mai same hun");
                    continue;

                } else {
                    try {
                        new PrintWriter(sRaW.getOutputStream(), true)
                                .println(mString);
                    } catch (IOException e) {

                        System.out.println("Its in Catch");

                    }
                }
            }

        }

    }

    class ByeByeKarDo implements Runnable {

        Socket inCom;

        public ByeByeKarDo(Socket si) {

            this.inCom = si;
        }

        @Override
        public void run() {

            try {
                new PrintWriter(inCom.getOutputStream(), true)
                        .println("You have Logged Out of Server... Thanks for your Visit");
            } catch (IOException e) {

                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new Server().go();
    }
}

Upvotes: 0

You are not using ServerSocket correctly. You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection. Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.
Something like (< condition met > is pseudo-code defines your condition to accept new connections):

while(< condition met >) {
    try {
        client = listener.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
        String str = br.readLine();
        //do something with str
    } finally {
        //close client socket
    }    
}

Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.

Upvotes: 2

Jack
Jack

Reputation: 133629

This because a ServerSocket is used as an entry point for a normal Socket. accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket. It sits there and waits for a new connection to spawn a new Socket which is then used for data.

This means that while receiving messages you should call just readLine() to read from the specific Socket. Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.

Socket socket = serverSocket.accept();

ClientThread thread = new ClientThread(socket);

class ClientThread extends Thread {
  Socket socket;

  public void run() {
    while (!closed) {
      String line = reader.readLine();
      ...
    }
  }

You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.

Upvotes: 2

Related Questions