如何向现有客户端之一发送消息?

问题描述 投票:0回答:1

我正在与一个大学项目进行聊天程序。我已经做到了,以使其正常工作。现在是实现登录的时候了,但是我担心安全性问题,因为我现在创建的结构会将消息发送给所有客户。

如何将消息发送到所有客户端线程,但是如何将消息发送到当前正在发送消息的客户端?

我将像这样向服务器发送消息

LOGIN#ID#PASSWORD#TIMESTAMP
TEXTSEND#TEXT
FUNCTION#FUNCTION_CHILD#FUNCTION_CHILD2#....

这是我的代码

服务器代码

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    final public String SELP_IP="127.0.0.1"; // Testing for My Computer IP
    public static ExecutorService threadPool;
    public static Vector<Client> clients = new Vector<Client>();
    ServerSocket serverSocket;

    //Run server and wait connection
    public void startServer(String IP, int port){
        try{
            serverSocket =new ServerSocket();
            serverSocket.bind(new InetSocketAddress(IP,port));
            System.out.println("server started!");
        }catch (Exception e){
            e.printStackTrace();
            if (serverSocket.isClosed()){
                stopServer();
            }
            return;
        }

        // new thread for waiting client connection
        Runnable thread = new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Socket socket=serverSocket.accept();
                        clients.add(new Client(socket));
                        System.out.println("[Client Connection]");
                        System.out.println(socket.getRemoteSocketAddress()+":"+Thread.currentThread().getName());
                    }catch (Exception e){
                        if(!serverSocket.isClosed()){
                            stopServer();
                        }
                        break;
                    }
                }
            }
        };
        threadPool= Executors.newCachedThreadPool();
        threadPool.submit(thread);
    }
    //this is for Stopping Server
    public void stopServer(){
        try{
            //Close All exsiting Socket
            Iterator<Client> iterator = clients.iterator();
            while (iterator.hasNext()){
                Client client=iterator.next();
                client.socket.close();
                iterator.remove();
            }
            //Close Server Object
            if(serverSocket!=null&&!serverSocket.isClosed()){
                serverSocket.close();
            }
            //Kill threadPool
            if (threadPool!=null&&!threadPool.isShutdown()){
                System.out.println("EXIT COMPLETE!");//DEBUG!!!!!!!!!!!!!!!!!
                threadPool.shutdown();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //UIrun
    public void start(){

    }

    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        Main m=new Main();
        m.startServer(m.SELP_IP,3306);
        if(in.next().equals("stop")){
            m.stopServer();
        }
    }

}

服务器端的客户端处理类

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client{
    Socket socket;
    public Client(Socket socket){
        this.socket=socket;
        recieve();
    }
    //message reciver
    private void recieve() {
        Runnable thread = new Runnable() {  //Using Multi Threading
            @Override
            public void run() {
                try {
                    while (true) {
                        InputStream in = socket.getInputStream();
                        byte[] buffer = new byte[512];
                        int length=in.read(buffer);
                        while (length==-1) throw new IOException();//Exception for Wrong input string
                        System.out.println("[MSG recieve SUCCESS!]");
                        System.out.println(socket.getRemoteSocketAddress()+":"+Thread.currentThread().getName()); //DEBUG
                        System.out.println();
                        String message=new String(buffer,0,length,"UTF-8");
                        System.out.println("Message from Client:"+message);

                        //Send message to All of other Client.
                        for(Client client : Main.clients){
                            client.send(message);
                        }

                    }
                }catch (Exception e){
                    try {
                        System.out.println("Client Connection END!");
                        System.out.println(socket.getRemoteSocketAddress()+":"+Thread.currentThread().getName());
                    }catch (Exception e2){
                        e2.printStackTrace();
                    }
                }
            }
        };
        Main.threadPool.submit(thread);
    }
    //sending messages to clients
    public void send(String msg){
        Runnable thread=new Runnable() {
            @Override
            public void run() {
                try{
                    OutputStream out = socket.getOutputStream();
                    byte[] buffer=msg.getBytes("UTF-8");
                    out.write(buffer);
                    out.flush();//.
                }catch (Exception e){
                    try{
                        System.out.println("Client Connection Lost!");
                        System.out.println(socket.getRemoteSocketAddress()+":"+Thread.currentThread().getName());
                        Main.clients.remove(Client.this);
                        socket.close();
                    }catch (Exception e2){
                        e2.printStackTrace();
                    }
                }
            }
        };
        Main.threadPool.submit(thread);
    }
}

java multithreading
1个回答
0
投票

“如何将消息发送到所有客户端线程,但是如何将消息发送到当前正在发送消息的客户端?”这句话令人困惑,但是我想您是在问如何仅将消息发送给特定的客户端。通常,在具有用户/登录名的系统中,您将为每个用户拥有唯一的密钥。假设它是您的示例中的loginId,对于您的代码示例,是否可以检查该循环中是否向当前客户端发送了一条消息,例如:

for(Client client : Main.clients){
   if (client.apply(message) {
     client.send(message);
   }
}

在apply(message)中,您可以检查这是否是给我的消息。

您当前的设计意味着只想传达一条信息,您必须循环所有客户,这对于学校项目来说应该可以,但是您可以考虑订户模式或广播。这些设计应更好地满足您的要求。另外,您可以使用一些消息队列,这也是一个好方法。

© www.soinside.com 2019 - 2024. All rights reserved.