Socket客户端与服务端通信私聊
来源:互联网 发布:windows 10 pro iso 编辑:程序博客网 时间:2024/05/19 13:25
客户端:
/** * 将聊天室客户端内容独立完成一次. * 下面内容可以选做: * 修改代码,使聊天室可以实现用户自定义昵称, * 以及私聊功能。 * * 参考思路: * 客户端连接服务端后,要求用户输入一个昵称, * 然后将改昵称发送给服务端,服务端那边读取到 * 客户端发送的第一个字符串认为是昵称。 * * 私聊功能可以定义格式,例如: * @张三:你好 * 服务端在读取客户端发送过来的昵称时,需要进行 * 解析,分解出昵称与聊天内容,然后将该聊天内容 * 单独发送给指定昵称的用户。 * 服务端的输出流需要使用Map进行维护,而不能再 * 使用List,Map的key可以是该用户昵称,value * 为该用户输出流。 * @author Xiloer * */public class Client {private Socket socket;public Client() throws IOException{socket=new Socket("176.195.107.88",8088);System.out.println("已连接服务器!");}private void inputNickName(Scanner scan) throws Exception{String nickName = null;//创建输出流PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"),true);//创建输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));while(true){System.out.println("请创建您的昵称:");nickName = scan.nextLine();if (nickName.trim().equals("")){System.out.println("昵称不得为空");}else {pw.println(nickName);String pass = br.readLine();if(pass!=null&&!pass.equals("OK")){System.out.println("昵称已经被占用,请更换!");break;}else{System.out.println("你好!"+nickName+"可以开始聊天了");break;}}}}public void start(){try {System.out.println("请输入:");Scanner scanner=new Scanner(System.in);inputNickName(scanner);ServerHandler server=new ServerHandler();Thread t=new Thread(server);t.start();OutputStream os = socket.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");PrintWriter pw = new PrintWriter(osw,true);while(true){pw.println(scanner.nextLine());}} catch (Exception e) {e.printStackTrace();}finally{if(socket !=null){try{socket.close();}catch(IOException e){e.printStackTrace();}}}}public static void main(String[] args) throws IOException {Client client=new Client(); client.start();} private class ServerHandler implements Runnable{public void run() {try {InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is,"UTF-8");BufferedReader br = new BufferedReader(isr);String msgString = null;while((msgString = br.readLine())!= null){System.out.println(msgString);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
服务端:
/** * 将聊天室服务端内容独立完成一次 * 下面内容可以选做: * 配合客户端实现支持昵称与私聊功能 * @author Xiloer * */public class Server {private ServerSocket server;//private List<PrintWriter> allOut;private Map<String,PrintWriter> allOut;public Server(){try {server=new ServerSocket(8088);allOut = new HashMap<String, PrintWriter>();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private void addOut(String key,PrintWriter value){synchronized(this){allOut.put(key, value);}}private synchronized void removeOut(String key){allOut.remove(key);System.out.println("当前在线人数为:"+ allOut.size());}private synchronized void sendMsgToAll(String message){for(PrintWriter out: allOut.values()){out.println(message);System.out.println("当前在线人数为:"+ allOut.size());}}private synchronized void sendMsgToPrivate(String nickname,String message){PrintWriter pw = allOut.get(nickname); //将对应客户端的聊天信息取出作为私聊内容发送出去if(pw!=null){pw.println(message);System.out.println("1111111111111111111111111111111111111");System.out.println("当前在线私聊人数为:"+ allOut.size());}}public void start(){try{while(true){System.out.println("等待客户端连接.......");Socket socket=server.accept();System.out.println("客户端已连接!");ClientHandler client=new ClientHandler(socket);Thread t=new Thread(client);t.start();}}catch(Exception e){e.printStackTrace();}}public static void main(String[] args) {Server server=new Server();server.start();}private class ClientHandler implements Runnable{ private Socket socket; private String host; private String nickName; public ClientHandler(Socket socket){ this.socket=socket; InetAddress adress=socket.getInetAddress(); host=adress.getHostAddress(); } private String getNickName() throws Exception{try{//服务端的输入流读取客户端发送来的昵称输出流InputStream in = socket.getInputStream();InputStreamReader isr = new InputStreamReader(in,"UTF-8");BufferedReader bReader = new BufferedReader(isr);//服务端将昵称验证结果通过自身的输出流发送给客户端OutputStream out = socket.getOutputStream();OutputStreamWriter iosw = new OutputStreamWriter(out,"UTF-8");PrintWriter ipw = new PrintWriter(iosw,true);//读取客户端发来的昵称String nameString = bReader.readLine();while(true){if(nameString.trim().length()==0){ipw.println("FAIL");}if(allOut.containsKey(nameString)){ipw.println("FAIL");}else {ipw.println("OK");return nameString;}}}catch(Exception e){throw e;}}public void run(){PrintWriter pw = null;try {/** 通过客户端的Socket获取客户端的输出流* 用来将消息发送给客户端*/OutputStream os = socket.getOutputStream();OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");pw = new PrintWriter(osw,true);/** 将客户昵称和其所说的话作为元素存入共享集合HashMap中*/nickName = getNickName();addOut(nickName, pw);Thread.sleep(100);/** 服务端通知所有客户端,某用户登录*/sendMsgToAll("[系统通知]:欢迎**"+nickName+"**登陆聊天室!");/** 通过客户端的Socket获取输入流* 读取客户端发送来的信息*/InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is,"UTF-8");BufferedReader br = new BufferedReader(isr);String msgString = null;while((msgString = br.readLine())!=null){//验证是否是私聊if(msgString.startsWith("@")){/** 私聊格式:@昵称:内容*/int index = msgString.indexOf(":");if(index >=0){//获取昵称String name = msgString.substring(1,index);String info = msgString.substring(index+1,msgString.length());info = nickName + "对你说:"+ info;//将私聊信息发送出去sendMsgToPrivate(name, info);//服务端不在广播私聊的信息continue;}System.out.println("已输出");}/** 遍历所有输出流,将该客户端发送的信息转发给所有客户端*/System.out.println(nickName+"说:"+ msgString);sendMsgToAll(nickName+"说:"+ msgString);} }catch (Exception e) {/** 因为Win系统用户的客户端断开连接后,br.readLine()方法读取* 不到信息就会抛出异常,而Linux系统会持续发送null;* 因此这里就不在将捕获的异常抛出了。*/}finally{/** 当执行到此处时,说明客户端已经与服务端断开连接* 则将该客户端存在共享集合中的输出流删除*/removeOut(nickName);/** 通知所有客户端,某某客户已经下线*/sendMsgToAll("[系统通知]:"+nickName + "已经下线了。");/** 关闭socket,则通过Socket获取的输入输出流也一同关闭了*/if(socket!=null){try{socket.close();}catch(IOException e){e.printStackTrace();}}}}} }
阅读全文
1 0
- Socket客户端与服务端通信私聊
- socket通信 客户端与服务端
- php服务端与android客户端socket通信
- php服务端与android客户端socket通信
- php服务端与android客户端socket通信
- 客户端与服务端Socket通信原理详解
- php服务端与android客户端socket通信
- 客户端与服务端的Socket通信
- socket客户端与服务端的通信
- Socket实现服务端与客户端通信
- socket实现客户端与服务端通信(一)服务端
- socket实现客户端与服务端通信(三)服务端升级
- socket实现客户端与服务端通信(二)客户端
- socket系列之socket服务端与客户端如何通信
- Socket服务端和客户端通信
- socket服务端和客户端通信
- Socket客户端与服务端
- socket通信-服务端-客户端-实现多个客户端群聊
- 实验一:基于STM32F1的流水灯实验(库函数)
- 学习jdbc(一周总结)
- 为什么ARM的启动代码是汇编?
- HDOJ 1203 I NEED A OFFER!(01背包)
- 空气动力与电机力学
- Socket客户端与服务端通信私聊
- 数塔问题练习5294_挖地雷
- 工厂模式的几种形态
- 2017年8月6日 星期日
- 运算符详解
- deepin安装mysql/navicat
- 寻找旋转排序数组中的最小值
- C#静态方法和非静态方法
- DOS命令