我正在与一个大学项目进行聊天程序。我已经做到了,以使其正常工作。现在是实现登录的时候了,但是我担心安全性问题,因为我现在创建的结构会将消息发送给所有客户。
如何将消息发送到所有客户端线程,但是如何将消息发送到当前正在发送消息的客户端?
我将像这样向服务器发送消息
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);
}
}
“如何将消息发送到所有客户端线程,但是如何将消息发送到当前正在发送消息的客户端?”这句话令人困惑,但是我想您是在问如何仅将消息发送给特定的客户端。通常,在具有用户/登录名的系统中,您将为每个用户拥有唯一的密钥。假设它是您的示例中的loginId,对于您的代码示例,是否可以检查该循环中是否向当前客户端发送了一条消息,例如:
for(Client client : Main.clients){
if (client.apply(message) {
client.send(message);
}
}
在apply(message)中,您可以检查这是否是给我的消息。
您当前的设计意味着只想传达一条信息,您必须循环所有客户,这对于学校项目来说应该可以,但是您可以考虑订户模式或广播。这些设计应更好地满足您的要求。另外,您可以使用一些消息队列,这也是一个好方法。