最近学习了Java的net包,看了网上的开源代码,整理了一部分服务端代码,实现了消息监听,直接上代码。
一。新建了一个消息类,用于存储消息进行传输
package com.xing.studyTest.net.im.model; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; /** * 消息信息 * @author xinghua * */ public class MessageBean implements Serializable{ private static final long serialVersionUID = 1L; private int type; // 1私聊 0上下线更新 -1下线请求 2请求发送文件 3.确定接收文件 private HashSet<String> clients; // 存放选中的客户 private HashSet<String> to;// public HashMap<String, MessageBean> onlines;// private String info;//信息 private String timer;//时间 private String name;//昵称 private String fileName;//文件名 private int size;//文件大小 private String ip;//IP private int port;//端口 public int getSize() { return size; } public void setSize(int size) { this.size = size; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public HashSet<String> getTo() { return to; } public void setTo(HashSet<String> to) { this.to = to; } public int getType() { return type; } public void setType(int type) { this.type = type; } public HashSet<String> getClients() { return clients; } public void setClients(HashSet<String> clients) { this.clients = clients; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public String getTimer() { return timer; } public void setTimer(String timer) { this.timer = timer; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public HashMap<String, MessageBean> getOnlines() { return onlines; } public void setOnlines(HashMap<String, MessageBean> onlines) { this.onlines = onlines; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return " [type=" + type + ", clients=" + clients + ", to=" + to + ", onlines=" + onlines + ", info=" + info + ", timer=" + timer + ", name=" + name + ", fileName=" + fileName + ", size=" + size + ", ip=" + ip + ", port=" + port + "]"; } }
二、因为要存储在线用户和用户连接信息,所以还需要个实体类
package com.xing.studyTest.net.im.model; import java.io.Serializable; import java.net.Socket; /** * 连接信息 * @author xinghua * */ public class SocketBean implements Serializable{ private static final long serialVersionUID = 1L; private String name;//名称 private Socket socket;//socket public String getName() { return name; } public void setName(String name) { this.name = name; } public Socket getSocket() { return socket; } public void setSocket(Socket socket) { this.socket = socket; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "ServerBean [name=" + name + ", socket=" + socket + "]"; } }
三,好了,接下来就是Server代码
package com.xing.studyTest.net.im.server; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import com.xing.studyTest.net.im.model.MessageBean; import com.xing.studyTest.net.im.model.SocketBean; /** * * @author xinghua * */ public class SocketServer { private static ServerSocket ss;//服务端服务对象 public static HashMap<String, SocketBean> onlines;//存储上线的Socket信息 //1.准备服务端对象及容器 static { try { ss = new ServerSocket(8520); onlines = new HashMap<String, SocketBean>();//新建一个容器存放客户端连接信息 } catch (IOException e) { e.printStackTrace(); } } //2.多线程实现监听消息处理 class CatClientThread extends Thread { private Socket socket;//链接 private MessageBean messageBean;//消息 private ObjectInputStream ois;//读取消息 private ObjectOutputStream oos;//输出消息 public CatClientThread(Socket socket) { this.socket = socket; } @Override public void run() { try { messageBean = (MessageBean)new ObjectInputStream(socket.getInputStream()).readObject(); System.out.println("获取消息对象:"+messageBean); //根据请求类型进行不同的操作 switch (messageBean.getType()) { case 0: { // 上线 System.out.println("上线1.记录上线客户的用户名和端口,组装用户名和Socket连接,添加到容器中"); SocketBean socketBean = new SocketBean(); socketBean.setName(messageBean.getName()); socketBean.setSocket(socket); onlines.put(messageBean.getName(), socketBean);//添加到onlines中 System.out.println("上线2.已存储上线,开始准备发送消息给客户端"); System.out.println("当前在线人数:【"+onlines.keySet().size()+"】个"); MessageBean returnMessageBean = new MessageBean(); returnMessageBean.setType(0); returnMessageBean.setInfo(messageBean.getTimer() + " [ " + messageBean.getName() + " ]上线了"); System.out.println("上线3.发送消息准备完毕,发送给全部用户:"); System.out.println(onlines.keySet()); // System.out.println(onlines.values()); HashSet<String> set = new HashSet<String>(); set.addAll(onlines.keySet()); returnMessageBean.setClients(set); sendAll(returnMessageBean); System.out.println("上线4.发送有人上线消息给全部用户完毕"); break; } case -1: { // 下线 // try { // oos = new ObjectOutputStream(socket.getOutputStream()); // oos.writeObject(messageBean); // oos.flush(); // } catch (IOException e) { // e.printStackTrace(); // } System.out.println("下线1.将用户从容器删除"); onlines.remove(messageBean.getName()); System.out.println("下线2.用户已移除,准备发送消息告诉所有人他下线了"); MessageBean returnMessageBean = new MessageBean(); returnMessageBean.setType(-1); returnMessageBean.setInfo(messageBean.getTimer() + " [ " + messageBean.getName() + " ]下线了"); System.out.println("下线3.发送消息准备完毕,发送给全部用户"); sendAll(returnMessageBean); System.out.println("下线4.发送有人下线消息给全部用户完毕"); break; } case 1: { // 聊天 System.out.println("聊天1.组装消息,准备给选中的用户发送"); MessageBean returnMessageBean = new MessageBean(); returnMessageBean.setType(1); returnMessageBean.setClients(messageBean.getClients()); returnMessageBean.setName(messageBean.getName());//选中的用户昵称 returnMessageBean.setInfo(messageBean.getInfo());//消息内容 returnMessageBean.setTimer(messageBean.getTimer());//发送时间 System.out.println("聊天2.组装消息准备完毕开始发送"); System.out.println(returnMessageBean); sendMessage(returnMessageBean); System.out.println("聊天3.发送消息完毕"); break; } case 2: { // 请求接受文件 break; } case 3: { // 确定接收文件 break; } default: { break; } } } catch (Exception e) { e.printStackTrace(); } finally { close(); } } // 向选中的用户发送数据 private void sendMessage(MessageBean messageBean) { // 首先取得所有的values Set<String> cbs = onlines.keySet(); Iterator<String> it = cbs.iterator(); // 选中客户 HashSet<String> clients = messageBean.getClients(); while (it.hasNext()) { // 在线客户 String client = it.next(); // 选中的客户中若是在线的,就发送 if (clients.contains(client)) { Socket c = onlines.get(client).getSocket(); ObjectOutputStream oos; try { oos = new ObjectOutputStream(c.getOutputStream()); oos.writeObject(messageBean); oos.flush(); } catch (IOException e) { e.printStackTrace(); } } } } /* * 向所有的用户发送数据 */ public void sendAll(MessageBean serverBean) { Collection<SocketBean> clients = onlines.values(); Iterator<SocketBean> it = clients.iterator(); ObjectOutputStream oos; while (it.hasNext()) { Socket c = it.next().getSocket(); try { oos = new ObjectOutputStream(c.getOutputStream()); oos.writeObject(serverBean); oos.flush(); } catch (IOException e) { e.printStackTrace(); } } } /* * 关闭Socket连接 */ private void close() { if (oos != null) { try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } if (ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } /* * 循环调用监听与本Socket的连接信息, */ public void start() { try { Executor executor = Executors.newFixedThreadPool(3); while (true) { String name = ss.getInetAddress().getHostName(); System.out.println("启动服务器监听程序启动完成,快来给我发送消息把!:host:"+name+"port:"+ss.getLocalPort()); Socket socket = ss.accept(); name = socket.getInetAddress().getHostName(); System.out.println("收到host:"+name+"port:"+socket.getPort()+"的消息处理开始"); Long timeStart = System.currentTimeMillis(); executor.execute(new CatClientThread(socket)); // new CatClientThread(socket).start(); System.out.println("收到host:"+name+"port:"+socket.getPort()+"的消息处理完毕,用时【"+(System.currentTimeMillis()-timeStart)+"】秒"); } } catch (IOException e) { e.printStackTrace(); } } }
四、最后启动:
package com.xing.studyTest.net.im.main; import com.xing.studyTest.net.im.server.SocketServer; /** * 启动服务端 * @author xinghua * */ public class ServerApplication { public static void main(String[] args) { new SocketServer().start(); } }
五、此时就在监听 等待客户端发消息来连接了
编辑
六、简单的客户端搞个上线信息发送:
package com.xing.studyTest.net.im.main; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; import com.xing.studyTest.net.im.model.MessageBean; /** * 客户端 * @author xinghua * */ public class ClientApplication2 { private static final String HOST = "localhost";//host private static final int PORT = 8520;//端口 private static final String NAME = "雅楠";//host public static void main(String[] args) { Socket socket = null; DataInputStream dataInputStream = null; DataOutputStream dataOutputStream = null; try { Scanner input = new Scanner(System.in); System.out.println("请输入一个昵称"); String name = input.nextLine(); System.out.println("你的昵称是【"+name+"】,开始连接。。。"); //上线 MessageBean messageBean = new MessageBean(); messageBean.setType(0); messageBean.setName(name); messageBean.setTimer(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); socket = new Socket(HOST, PORT); // System.out.println("发起请求到->"+HOST+":"+PORT); ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); oos.writeObject(messageBean); oos.flush(); System.out.println("获取响应数据"); MessageBean resMB = (MessageBean)new ObjectInputStream(socket.getInputStream()).readObject(); System.out.println(resMB); System.out.println(); } catch (Exception e) { e.printStackTrace(); } finally { try { if(dataInputStream != null){ dataInputStream.close(); } if(dataOutputStream != null){ dataOutputStream.close(); } if(socket != null){ socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
这是搞了个上线消息发送,并收到响应,客户端应该是不停的监听服务端发送消息,以实现聊天,还没写出来,下次再贴出来吧
编辑
好吧,自己发给自己了,啊哈哈哈哈
编辑