文章评分
次,平均分 :
[收起]
文章目录
这是SSD8练习的Exam1,预计极客人将会写一个系列,更新频率会和NWPU网络与分布式计算实验课2013级进度同步。点击标签或在本站搜索“SSD8”即可获取已更新的SSD8答案。上一练习:SSD8_EX2【UDP vs TCP】;如果你想继续跟踪SSD练习进展,建议订阅本站。
本次练习采用多线程、TCP通信协议制作一个多人聊天软件,将用户上线下线消息、正常交流信息对所有连接的用户进行广播。极客人的主要思维是建立socket的hashmap,遍历hashmap与众多客户端通信。
一、实验题目
根据题目下文给出的聊天协议列表,使用Java sockets实现一个简单的TCP聊天服务器。该服务器应该具有以下功能:
1. 从每一个客户端(client)读取信息;
2. 能将读取的信息转发给所有客户端;
3. 通过命令行获得端口(port)信息;
4. 监听特定端口(port)的请求信息;
5. 能够处理并发连接,即需要使用多线程来处理每一个连接。
题中已经提供了一个图形化客户端GUIClient.jar。
GUIClient.jar反编译文件在“相关下载中”,这是客户端的源代码
二、Chat Server服务器端代码
Chat Server.java:
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
package cn.wangbaiyuan; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.StringTokenizer; /** * ChatServer类启动服务器服务 * * @author <a href="http://wangbaiyuan">王柏元</a> *代码为<a href="http://wangbaiyuan">王柏元</a>原创,并同步发布在 *<a href="http://wangbaiyuan.cn/ssd8-exam1%e3%80%90tcp-chat-server%e3%80%91.html">王柏元的博客</a>转载请注明来源 */ public class ChatServer { private static HashMap<String, Socket> serverSocketMap = new HashMap<String, Socket>(); ServerSocket serverSocket; private int port = 1234; /** * 启动聊天服务端服务 * @throws IOException 抛出IOException */ public ChatServer() throws IOException { serverSocket = new ServerSocket(port); System.out.println("ChatServer服务器启动……"); } public void service() { while (true) { Socket socket = null; try { socket = serverSocket.accept(); Thread work = new Thread(new Handler(socket)); // 为客户连接创建工作线程 work.start(); } catch (IOException e) { e.printStackTrace(); } } } /** * 处理子线程类 * @author <a href="http://wangbaiyuan">王柏元</a> *代码为<a href="http://wangbaiyuan">王柏元</a>原创,并同步发布在 *<a href="http://wangbaiyuan.cn/ssd8-exam1%e3%80%90tcp-chat-server%e3%80%91.html">王柏元的博客</a>转载请注明来源 */ public class Handler implements Runnable { // 负责与单个客户通信的线程 private Socket socket; DataInputStream br; DataOutputStream bw; PrintWriter pw; public Handler(Socket socket) throws UnsupportedEncodingException, IOException { this.socket = socket; } @SuppressWarnings("deprecation") /** * 有新连接时初始化,并向已连接用户广播信息 * @throws IOException */ public void initStream() throws IOException { // 初始化输入输出流对象方法 br = new DataInputStream(socket.getInputStream()); bw = new DataOutputStream(socket.getOutputStream()); String str1 = br.readUTF(); System.out.println(str1); StringTokenizer localStringTokenizer1 = new StringTokenizer(str1, "^");//分割字符串 try { String head = localStringTokenizer1.nextToken(); System.out.println(head); String nameIP = localStringTokenizer1.nextToken(); StringTokenizer localStringTokenizer2 = new StringTokenizer( nameIP, "@"); String name = localStringTokenizer2.nextToken(); serverSocketMap.put(name, socket); String ip = localStringTokenizer2.nextToken(); String member = localStringTokenizer1.nextToken(); String message = localStringTokenizer1.nextToken(); String message_join = "m^system@10.22.56.186^all^" + name + " has joined from " + ip + "__[time:" + nowTime() + "]^"; sentoAll(name, message_join); } catch (NoSuchElementException localNoSuchElementException) { System.out.println("GUIClient: No Such Element Exception"); } } /** * 群发消息 * @param name * 群发消息的消息源-昵称 * @param message * 群发消息的消息 * @throws IOException */ public void sentoAll(String name, String message) throws IOException { Iterator iterator = serverSocketMap.keySet().iterator(); while (iterator.hasNext()) { String key = (String) iterator.next(); Socket received = serverSocketMap.get(key); bw = new DataOutputStream(received.getOutputStream()); bw.writeUTF(message); } } /** * 获取当前时间 * @return 当前时间 */ public String nowTime() { Calendar c = Calendar.getInstance(); c.setTimeInMillis(new Date().getTime()); SimpleDateFormat dateFormat = new SimpleDateFormat( "yy-MM-dd HH:mm:ss"); return dateFormat.format(c.getTime()); } /** * 执行发送内容 */ public void run() { // 执行的内容 try { System.out.println(socket.getInetAddress() + "加入了群聊"); initStream(); // 初始化输入输出流对象 String info = null; while (null != (info = br.readUTF())) { StringTokenizer localStringTokenizer1 = new StringTokenizer( info, "^"); try { String head = localStringTokenizer1.nextToken(); String nameIP = localStringTokenizer1.nextToken(); StringTokenizer localStringTokenizer2 = new StringTokenizer( nameIP, "@"); String name = localStringTokenizer2.nextToken(); String ip = localStringTokenizer2.nextToken(); String member = localStringTokenizer1.nextToken(); String message = localStringTokenizer1.nextToken(); if (head.equals("m")) { String message_exchange = "m^" + name + "@10.22.56.186^all^" + message + "___[time:" + nowTime() + "]^"; sentoAll(name, message_exchange); } else if (head.equals("j")) { String message_join = "j^system@10.22.56.186^all^" + name + " has joined from " + ip + "___[time:" + nowTime() + "]^"; sentoAll(name, message_join); } else if (head.equals("p")) { String message_exit = "m^system@10.22.56.186^all^" + name + " has leaved! ___[time:" + nowTime() + "]^"; serverSocketMap.remove(name); sentoAll(name, message_exit); } } catch (NoSuchElementException localNoSuchElementException) { System.out .println("GUIClient: No Such Element Exception"); } System.out.println(info); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != socket) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } public static void main(String[] args) throws IOException { new ChatServer().service(); // 启动服务 } } |
相关下载

关注我的微信,获取文章更新
如果你觉得这篇文章对你有用,可以点击下面的“赞助作者”打赏作者!
转载注明原文出处:王柏元的博客>>https://wangbaiyuan.cn/ssd8-exam1%e3%80%90tcp-chat-server%e3%80%91.html
暂无评论