简体   繁体   中英

Client-Server-Client communication using Sockets

I am building a small chat application in which client A wants to send something to client C with server B in between. First of all is this a correct approach for the problem??. I am able to send and receive data to and from a server but it is limited to only the client.For example if Client A sends data to server B and client C is sending data to server B then i can send data back to A and C just like an echo server. But what i want is to forward data coming from Client A to Client C via server B.

The following is the server code:

public class Server {
    public static void main(String[] args) {
        int port = 666; //random port number
        try {
            ServerSocket ss = new ServerSocket(port);
            System.out.println("Waiting for a client....");

            System.out.println("Got a client :) ... Finally, someone saw me through all the cover!");
            System.out.println();
            while(true) {
                Socket socket = ss.accept();

                SSocket sSocket = new SSocket(socket);
                Thread t = new Thread(sSocket);
                t.start();
                System.out.println("Socket Stack Size-----"+socketMap.size());
            }
        }
        catch (Exception e) { }
    }
}

class SSocket implements Runnable {
    private Socket socket;

    public SSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();

            DataInputStream dIn = new DataInputStream(in);
            DataOutputStream dOut = new DataOutputStream(out);

            String line = null;
            while (true) {
                line = dIn.readUTF();
                System.out.println("Recievd the line----" + line);
                dOut.writeUTF(line + " Comming back from the server");
                dOut.flush();
                System.out.println("waiting for the next line....");    
            }
        }
        catch (Exception e) { }
    }
}

The client code is :

public class Client {
    public static void main(String[] args) {
        int serverPort = 666;

        try {
            InetAddress inetAdd = InetAddress.getByName("127.0.0.1");
            Socket socket = new Socket(inetAdd, serverPort);

            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();

            DataInputStream dIn = new DataInputStream(in);
            DataOutputStream dOut = new DataOutputStream(out);

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

            System.out.println("Type in something and press enter. Will send it to the server and tell ya what it thinks.");
            System.out.println();

            String line = null;
            while (true) {
                line = keyboard.readLine();
                System.out.println("Wrinting Something on the server");
                dOut.writeUTF(line);
                dOut.flush();

                line = dIn.readUTF();
                System.out.println("Line Sent back by the server---" + line);
            }
        }
        catch (Exception e) { }
    }
}

When your clients connect to the server, your server creates a Socket for it, here it is Socket socket = ss.accept(); , your socket variable will be holding that client.

now if you just keep adding your client socket to a arraylist in your while loop, you will have a list of clients actively connected with your server like:

after the accept:

clients = new ArrayList<DataOutputStream>();
Socket socket = ss.accept();
os = new DataOutputStream(socket.getOutputStream());
clients.add(os);

Now as you have all the clients in that clients arraylist, you can loop through it, or with some protocol define which client should i send the data after reading.

Iterator<DataOutputStream> it = clients.iterator();
while ((message = reader.readLine()) != null) { //reading    
    while (it.hasNext()) {
        try {
            DataOutputStream oss = it.next();
            oss.write(message);//writing
            oss.flush();
        }
        catch (Exception e) { }
     }
 }

This will loop through all the available clients in the arraylist and will send to all. you can define ways to send to only some.

For example: maintain a ActiveClients arraylist and with some GUI interaction may be or maybe, define what all clients you want to send the message. Then add just those clients outputStreams to ActiveClients

ActiveClients.add(clients.get(2));

or remove them, if you don't want them.

ActiveClients.remove(clients.get(2));

and now just loop through this arraylist to send the data as above.

You can create message queue for each client:

  1. Client A sends message 'Hi' with address Client C to server B.
  2. Server B receives message and adds it to message queue of client C.
  3. Thread in server B which communicates with client C check message queue, retrieve message and sends it to client C.
  4. Client C receives message.

If I am not mistaken, you must be having a problem with receiving a message from the Server or SSocket class. What happens with your code is that when you send a message from the client to the server the Server class receives your messages also gives an echo of the message in the client. However, when you send a message from the Server class, you don't get any messages in the Client Class.

To get this to work, you would have to modify your code in the following fashion:

SSocket Class

String line = null;
while (true) {
    line = dIn.readUTF();
    System.out.println("Recievd the line----" + line);
    dOut.writeUTF(line + " Comming back from the server");
    dOut.flush();
    System.out.println("waiting for the next line....");
}

You should add these lines:

String Line2 = take.nextLine(); //The user types a message for the client
dOut.writeUTF(Line2 + " Comming back from the server"); //The message is sent to the client

Replace the while loop with this one and it will work fine.

while (true) {       
    line = dIn.readUTF(); //Takes the msg from the client
    System.out.println("Recievd the line----" + line); //Prints the taken message

    String Line2 = take.nextLine(); //The user types a message for the client
    dOut.writeUTF(Line2 + " Comming back from the server"); //The message is sent to the client
    dOut.flush();
    System.out.println("waiting for the next line....");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM