websocket实现群发图片

流程:
(群发图片)
1.前台获取并连接websocket服务器,上传图片,将流、图片流通过websocket发送至服务器。

2.后台搭建websocket服务器,以及消息处理服务,将接收到的图片流转发给所有在线客户端。

3.客户端收到服务器转发的图片流,动态添加img标签,将图片在页面上展示。

效果:
1.未发图片时图片列表为空
未发图片时的效果
2.发送图片,在线的客户端都会收到图片消息。
在这里插入图片描述

实现过程:
1.前台代码:
(1)html代码

<!--发送图片按钮-->
    <form name="form1">
        <input type="file" name="picpath" id="choose-img" style="display:none;" onChange="setImagePreview()">
        <input name="path" style="display:none;" readonly>
        <input type="button" value="发送照片" onclick="document.form1.picpath.click()"> 
    </form>
<!--收到的图片列表-->
<div id="show"><h3>图片列表:</h3></div>

(2)js代码(收到服务端的图片流后动态添加img标签,将图片显示在页面上)

//获取并建立websocket连接
    get("/getWebSocketUrlImg")
        .then((data) => {
            if (!websocketImg) {
                websocketImg = new WebSocket(data.url);
                log("websocket连接成功Image服务器")
            }
            websocketImg.onopen = () => {
                 log("open")
            };
            websocketImg.onclose = () => {
                log("Connection closed.");
            };
            websocketImg.onerror = () => {
                log("websocket error");
            };
            //收到消息后动态添加img标签,显示在页面上
            websocketImg.onmessage = function(event){
                var reader = new FileReader();
                reader.onload=function(eve){
                    if(eve.target.readyState==FileReader.DONE)
                    {
                        var img = document.createElement("img");
                        img.src=this.result;
                        img.height=300;
                        img.width=500;
                        document.getElementById("show").appendChild(img);
                    }
                };
                reader.readAsDataURL(event.data);
            };
        });
//上传按钮触发的方法
	function setImagePreview() {
	    var file = document.getElementById('choose-img').files[0];
	    var reader = new FileReader();
	    reader.readAsArrayBuffer(file);
	
	    reader.onload = function(e) {
	        var rawData = e.target.result;
	         // websocketImg.send(rawData);
	        websocketImg.send(rawData);
	    };
	    // websocketImg.send("asdasdadsadasdasda");
}
//get请求封装
//get 请求
const get = (url,params) => {
    if (params) {
        let paramsArray = [];
        //拼接参数
        Object.keys(params).forEach(key =>
            paramsArray.push(key + '=' + encodeURI(params[key].toString())));

        if (paramsArray.length > 0) {
            if (url.search(/\?/) === -1) {
                url += '?' + paramsArray.join('&');
            } else {
                url += '&' + paramsArray.join('&');
            }
        }
    }
    return new Promise((resolve, reject) => {
        fetch(url)
            .then(res => res.json())
            .then(data => resolve(data))
            .catch(err => reject(err));
    });
};

2.后端代码
(1)get请求地址,返回链接

    @GetMapping("/getWebSocketUrlImg")
    public Map<String, String> getIpAddressImg(HttpServletRequest request) {
        Map<String, String> result = new HashMap<>(1);
        if(IP_CODE.equals(request.getRemoteAddr())){
            //本地访问
            result.put("url", "wss:"+request.getRemoteAddr()+":"+port+ "/sendImage");
        }else{
            //服务IP访问
            result.put("url", "wss:" + "192.168.1.178" +":"+port+ "/sendImage");
        }
        return result;
    }

(2)websocket图片服务器

@ServerEndpoint(value = "/sendImage", configurator = ConfiguratorForClientIp.class)
@Component
@Slf4j
public class ImgMessage{
        /**
         * 在线总人数
         */
        private static volatile AtomicInteger onlineCount = new AtomicInteger(0);
        private static RoomService roomService;
        private static MessageService messageService;
        @Autowired
        public void setRoomService(RoomService roomService) {
                ImgMessage.roomService = roomService;
        }
        @Autowired
        public void setMessageService(MessageService messageService) {
                ImgMessage.messageService = messageService;
        }
        /**
         * 某个客户端的ip
         */
        private String ip;
        /**
         * 与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
        private Session session;


        @OnMessage(maxMessageSize = 5000000)
        public void getMessage(Session session , byte[] stringMessage) throws IOException {
                messageService.sendImgMessageForEveryInRoom(stringMessage);
        }
        
        @OnOpen
        public void start(Session session){
                this.session = session;
                ip = (String) session.getUserProperties().get("clientIp");
                //将本次连接放到大厅里面
                roomService.enterLobbyImg(this);
                log.info("用户: {}, 连接到服务器,当前在线人数为:{}", ip, onlineCount.incrementAndGet());
        }
}

(3)房间处理服务(只有大厅,可以按照自己的逻辑扩展业务,添加多个房间)

@Service
public class RoomService {

    private Map<String, Set<ImgMessage>> roomsImg = new ConcurrentHashMap<>();
    
    /**
     * 加入到大厅
     */
    public void enterLobbyImg(ImgMessage connection) {
        Set<ImgMessage> lobby = roomsImg.get("lobby");
        if (lobby == null) {
            roomsImg.put("lobby", new HashSet<>());
            lobby = roomsImg.get("lobby");
            lobby.add(connection);
        } else {
            lobby.add(connection);
        }
    }
    
    
    /**
     * 离开大厅
     */
    public void leaveLobby(Connection connection) {
        Set<Connection> lobby = rooms.get("lobby");
        lobby.remove(connection);
    }
    
}

(4)消息处理服务(只有图片处理方法,可以根据自己需求处理其他消息,例如文本,文件等)

/**
 * 消息处理服务
 */
@Slf4j
@Service
public class MessageService {
    @Autowired
    private RoomService roomService;
    
    /**
     * 给房间内的所有人发送图片(包括自己)
     */
    public void sendImgMessageForEveryInRoom(byte[] message) throws IOException {
        Set<ImgMessage> room = roomService.queryRoomByIdImg("lobby");
        room.stream().forEach(t->{
            try {
                t.getSession().getBasicRemote().sendBinary(ByteBuffer.wrap(message));
            } catch (IOException e) {

            }
        });
    }
}
  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Spring Boot实现WebSocket发消息的步骤: 1.添加pom依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2.配置WebSocket和监听器 在Spring Boot的配置类中添加以下配置: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new MyWebSocketHandler(), "/websocket").setAllowedOrigins("*"); } @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } @Bean public HttpSessionConfigurator httpSessionConfigurator() { return new HttpSessionConfigurator(); } } ``` 其中,MyWebSocketHandler是自定义的WebSocket处理器,用于处理WebSocket连接和消息的发送和接收。 3.编写WebSocket处理器 ```java @Component public class MyWebSocketHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(message); } } } ``` 在这个处理器中,我们使用了一个静态的sessions列表来保存所有连接到WebSocket服务器的会话。在连接建立时,我们将会话添加到sessions列表中。在连接关闭时,我们将会话从sessions列表中移除。在处理文本消息时,我们遍历sessions列表,并将消息发送到每个会话。 4.启动应用程序 在Spring Boot的启动类中添加@EnableWebSocket注解,以启用WebSocket支持。 ```java @SpringBootApplication @EnableWebSocket public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 5.测试 使用浏览器或WebSocket客户端连接到WebSocket服务器的URL(例如:ws://localhost:8080/websocket),并发送消息。所有连接到服务器的会话都将收到相同的消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值