一.需求
需求如题. 当多个客户端连接服务器时,服务器如何给指定的客户端发送消息.
二.解决方案
核心思想: 在服务器端,需保存不同客户端的socket列表及客户端相关信息.
socket含有发送方和接收方的ip和端口号,所以通过socket就能向指定的客户端发送消息.
经查阅资料,得到如下解决方案:
- 用户连接时,立即向服务器发送自己的唯一ID,服务器端将ID和对应的socket用map存储. 向客户端发送消息时,就可以通过ID,找到对应的socket,然后向其发送消息.
- 如果客户端ip固定,服务器每收到一个Socket都用Map存起来.
三.实践
说明:采用第一种解决方案,模拟服务器向指定的客户端发送消息.
服务端循环监听,第一个服务器进来,向其发送其自身序号,第二个进来,遍历socke列表,向列表中的每一个客户端发送其对应的序号,从而达到服务器向指定客户端发送消息的功能.
服务器端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package server; import java.io.*; import java.net.*; import java.util.HashMap; * 主函数,实现服务器向指定客户端发送消息的功能. * 客户端用python书写 * @author dingding * */ public class Run { private final static int PORT = 30000; public static HashMap<String, Socket> socketList = new HashMap<>(); public static String channelToken; private static BufferedReader bufferedReader; public static void main(String[] args) { try { ServerSocket server = new ServerSocket(PORT); System.out.println("server is listenning..."); while(true){ Socket clientSocket = server.accept(); bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); channelToken = bufferedReader.readLine(); socketList.put(channelToken,clientSocket); new ServerThread(clientSocket,socketList); } } catch (IOException e) { e.printStackTrace(); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| package server; import java.io.*; import java.net.*; import java.util.*; public class ServerThread extends Thread{ private Socket client; private PrintWriter out; private HashMap<String, Socket> clientList = new HashMap<>(); public ServerThread(Socket socket,HashMap<String, Socket> socketList) throws IOException{ super(); client = socket; clientList = socketList; start(); } @Override public void run(){ Socket socket; System.out.println("Client: "+getName()+" come in..."); Iterator<HashMap.Entry<String, Socket>> entries = clientList.entrySet().iterator(); while (entries.hasNext()){ HashMap.Entry<String, Socket> entry = entries.next(); System.out.println(entry.getKey()); if (!String.valueOf(entry.getKey()).equals("")) { System.out.println(entry.getValue()); System.out.println("-------------"); socket = entry.getValue(); if (socket!=null) { try { out = new PrintWriter(socket.getOutputStream()); out.println(entry.getKey()); out.flush(); } catch (IOException e) { e.printStackTrace(); } } } } } }
|
两个客户端
用两个python客户端来模拟场景.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import socket import threading HOST = "localhost" PORT = 30000 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) def test(): socketID = 'I am 111' sock.sendall((socketID+'\r').encode()) while True: data = sock.recv(1024).decode() print('from line: '+data) sock.close() if __name__ == '__main__': test()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import socket import threading HOST = "localhost" PORT = 30000 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) def test(): socketID = 'I am 000' sock.sendall((socketID+'\r').encode()) while True: data = sock.recv(1024).decode() print('from line: '+data) sock.close() if __name__ == '__main__': test()
|
四.总结
socket 服务器向指定的客户端发消息,网上给的资源不多,大多是关于服务器群发. 这里给出了具体解决方案,并通过实例证实了该方案的可行性.
有时看的资料越多,越不明白.这并总是好事.
这个时候就需要静下来理理思路,然后针对具体的解决方案,编程实现.
实践才是检验真理的唯一标准,设计代码的时候你就离成功又近了一步.
参考文献
- java socket编程中,如何让服务器主动向指定ip地址的客户端发送信息
- socket 服务器给指定的客户端发消息该怎么处理
- socket 服务器给指定的客户端发消息该怎么处理