• 基于Socket实现多人聊天室


    当前支持:

    1.仅文字

    2.加入聊天室提醒

    3.退出聊天室提醒

    可能出现的BUG:

    1.可能出现客户端发送信息后不能及时推送,需要下一个客户端发送信息后一起推送

    服务端代码:

      1 package com.example.demo.socket;
      2 
      3 import org.springframework.util.ObjectUtils;
      4 
      5 import java.io.DataInputStream;
      6 import java.io.DataOutputStream;
      7 import java.io.IOException;
      8 import java.net.ServerSocket;
      9 import java.net.Socket;
     10 import java.util.HashMap;
     11 import java.util.Map;
     12 import java.util.concurrent.*;
     13 
     14 public class Server {
     15     public static void main(String[] args) {
     16         //信息队
     17         ConcurrentLinkedQueue str = new ConcurrentLinkedQueue<>();
     18         //连接对,暂未使用
     19         ConcurrentLinkedQueue<Map> socket = new ConcurrentLinkedQueue<>();
     20         //信息接收队
     21         ConcurrentLinkedQueue<Map> ins = new ConcurrentLinkedQueue<>();
     22         //信息发送队
     23         ConcurrentLinkedQueue<Map> outs = new ConcurrentLinkedQueue<>();
     24         //服务端端口号
     25         int port = 6666;
     26         try {
     27             ServerSocket serverSocket = new ServerSocket(port);
     28             //读取信息
     29             new Thread(new Runnable() {
     30                 @Override
     31                 public void run() {
     32                     // 参数 4 可以根据实际服务器cup设置 一般IO密集型设置为 CUP+1
     33                     ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
     34                     while (true) {
     35                         if(!ObjectUtils.isEmpty(ins.peek())) {
     36                             Map in = ins.poll();
     37                             //延迟10毫秒执行,执行周期为  实际线程执行时间+10毫秒
     38                             ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
     39                                 @Override
     40                                 public void run() {
     41                                     try {
     42                                         in.put("str", ((DataInputStream) in.get("in")).readUTF());
     43                                         str.add(in);
     44                                     } catch (IOException e) {
     45                                         ((ScheduledFuture)in.get("future")).cancel(true);
     46                                     }
     47                                 }
     48                             }, 10, 10, TimeUnit.MICROSECONDS);
     49                             in.put("future",scheduledFuture);
     50                         }
     51                     }
     52                 }
     53             }).start();
     54             //发送信息
     55             new Thread(new Runnable() {
     56                 @Override
     57                 public void run() {
     58                     while (true) {
     59                         if(!ObjectUtils.isEmpty(str.peek())) {
     60                             Map o = (Map) str.poll();
     61                             for(Map m : outs) {
     62                                 if(!o.get("client").equals(m.get("client"))) {
     63                                     try {
     64                                         ((DataOutputStream)m.get("out")).writeUTF( o.get("client")+":"+o.get("str"));
     65                                     } catch (IOException e) {
     66                                         //异常下线大法,并发送群体下线通知
     67                                         System.out.printf("%s下线了!
    ",m.get("client"));
     68                                         Map sv = new HashMap<>();
     69                                         sv.put("client","server");
     70                                         sv.put("str",m.get("client")+"退出聊天室!");
     71                                         str.add(sv);
     72                                         outs.remove(m);
     73                                     }
     74                                 }
     75                             }
     76                         }
     77                     }
     78                 }
     79             }).start();
     80             //循环获取客户端连接
     81             while (true) {
     82                 Socket server = serverSocket.accept();
     83                 Map m = new HashMap<>();
     84                 m.put("socket",socket);
     85                 m.put("in",new DataInputStream(server.getInputStream()));
     86                 m.put("out",new DataOutputStream(server.getOutputStream()));
     87 
     88                 //向客户端发送聊天室名,并获取客户端连接名
     89                 ((DataOutputStream)m.get("out")).writeUTF("6666");
     90                 m.put("client",((DataInputStream)m.get("in")).readUTF());
     91                 System.out.printf("新人%s加入聊天室!
    ",m.get("client"));
     92 
     93                 ins.add(m);
     94                 outs.add(m);
     95                 socket.add(m);
     96 
     97                 //发送群体上线通知
     98                 Map sv = new HashMap<>();
     99                 sv.put("client","server");
    100                 sv.put("str",m.get("client")+"加入聊天室!");
    101                 str.add(sv);
    102             }
    103         } catch (Exception e) {
    104             e.printStackTrace();
    105         }
    106     }
    107 }
    Server

    客户端代码:

     1 package com.example.demo.socket;
     2 
     3 import java.io.DataInputStream;
     4 import java.io.DataOutputStream;
     5 import java.io.IOException;
     6 import java.net.Socket;
     7 import java.util.Scanner;
     8 
     9 public class Client {
    10 
    11     public static void main(String[] args) {
    12         //服务端 IP
    13         String serverName = "localhost";
    14         //服务端 端口号
    15         int port = 6666;
    16         try {
    17             Socket client = new Socket(serverName,port);
    18             DataInputStream in = new DataInputStream(client.getInputStream());
    19             DataOutputStream out = new DataOutputStream(client.getOutputStream());
    20             //向服务端发送连接名,并确认服务端收到连接名且返回聊天室名
    21             out.writeUTF("client");
    22             out.flush();
    23             System.out.printf("进入聊天室 %s 
    ",in.readUTF());
    24             try {
    25                 new Thread(new Runnable() {
    26                     @Override
    27                     public void run() {
    28                         try {
    29                             while (true) {
    30                                 System.out.println(in.readUTF());
    31                             }
    32                         } catch (IOException e) {
    33                             e.printStackTrace();
    34                         }
    35                     }
    36                 }).start();
    37                 while (true) {
    38                     out.writeUTF(new Scanner(System.in).nextLine());
    39                     out.flush();
    40                 }
    41             } finally {
    42                 client.close();
    43             }
    44         } catch (Exception e) {
    45             e.printStackTrace();
    46         }
    47 
    48     }
    49 }
    Client
  • 相关阅读:
    设计模式的原则
    List是线程安全的吗?如果不是该怎么办呢?安全的List对性能的影响有多大呢?
    StringBuilder是不是线程安全的?
    并行运算和普通运算之性能比较
    分布式与集群的区别
    sql查询性能分析
    C#代码实现,确保windows程序只有一个实例(instance)
    jQuery UI
    开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo
    整理的一些学习网站资料
  • 原文地址:https://www.cnblogs.com/tangzeqi/p/14752041.html
Copyright © 2020-2023  润新知