精华内容
下载资源
问答
  • java实现即时通讯代码

    2019-03-25 09:48:26
    本程序使用的是 TCP 协议实现即时通信软件,程序是基于 Java 语言开发的,主要用到的技术有: Socket 编程 自定义协议 如果使用普通的方法来标记一条消息的结束,如换行符,那么程序就不易扩展,只能发送纯文本...
  • 基于 Java 实现即时通讯软件 答辩者 XXX 指导老师 XX 班级 XXX 基于 Java 实现即时通讯系统 ? ? ? ? ? 研究背景 目的及意义 开发环境 系统设计 系统实现 研究背景 1. 即时通信改变人们的生活方式 2. 即时通讯优势 ( ...
  • java实现即时通讯

    2018-12-21 22:31:54
    java实现即时通讯:客户端通过socket连接服务器和其他客户端socket线程通信
  • 该demo是基于html5的WebSocket协议开发的聊天室,用java实现,本人亲测,可直接导入myeclipse中使用。
  • JavaQQ程序是通过多线程实现了一个服务器同时与多个客户机通信的程序。 Server类实现当程序开始运行时,会把相应的端口port设置为服务器。并让其处于待连接状态。每当有客户机连接上来时,就实例化一个线程类...
  • Java实现通讯系统,不是本人做的。。。
  • java实现即时通讯软件

    千次阅读 多人点赞 2021-01-06 22:49:22
    使用eclipse作为即时通讯软件的开发工具,使用Socket建立通讯渠道,多线程实现多台计算机同时进行信息的传递,swing技术等进行实际开发相对比较合适。通过一些轻松的注册登录后,在局域网中即时聊天便可以成功进行。...

    导读:即时通讯软件即所谓的聊天工具,其主要用途是用于文字信息的传递与文件传输。使用eclipse作为即时通讯软件的开发工具,使用Socket建立通讯渠道,多线程实现多台计算机同时进行信息的传递,swing技术等进行实际开发相对比较合适。通过一些轻松的注册登录后,在局域网中即时聊天便可以成功进行。

     

    目录

     

    项目结构:

     项目截图:

    展开全文
  • 导读:即时通讯软件即所谓的聊天工具,其主要用途是用于文字信息的传递与文件传输。使用eclipse作为即时通讯软件的开发工具,使用Socket建立通讯渠道,多线程实现多台计算机同时进行信息的...

    导读:即时通讯软件即所谓的聊天工具,其主要用途是用于文字信息的传递与文件传输。使用eclipse作为即时通讯软件的开发工具,使用Socket建立通讯渠道,多线程实现多台计算机同时进行信息的传递,swing技术等进行实际开发相对比较合适。通过一些轻松的注册登录后,在局域网中即时聊天便可以成功进行。

     


    项目结构:

     

    项目截图:

     


    总结:

    随着信息社会的快速发展,网络作为改变世界的最重要的因素。众多的企业纷纷使用局域网聊天来满足工作与交流高效、快速执行的需求。企业中使用内部局域网可以使内部信息交互的过程得以简化,从而达到提高工作效率的目的。所以经上所述,公司内部使用即时通讯的方式在各台计算机之间进行交流已经是时代发展的趋势。

    即时通讯软件即所谓的聊天工具,作为进行文字传输、文件传输的工具被使用在互联网的客户端上。从专业角度来介绍,即时通讯软件一般分为依赖于服务器的与依赖于P2P的。

    从现状来看,互联网上深受用户喜爱的即时通讯软件主要有以下几个:微信、QQ、YY、飞秋等等。

    如今的社会是信息社会,正是因为用户大量的需求促进了即时通讯的开发,信息快速的传递越来越受到重视同时使得互联网技术越来越成熟,在其中即时通讯软件承担了相当一部分的作用,在这些软件中,一些优秀且易用的聊天工具被各位用户所喜爱[3]。在中国,腾讯QQ无疑取得了极大的成功,简单易用,功能齐全,在满足用户基本需求的同时为各位用户提供其它使人称心的功能。即时通讯软件之所以能够取得成功,正是因为其适应了时代,符合了信息时代用户的需求,它不仅可以提供全面,大量信息给用户,同时也可以使用户的生活更加的精彩,成功满足了自身商业利益的获取也构建了人们和谐便利的生活。

    Socket是即时通讯系统实现的核心技术,可以通过端口设置与IP地址来构建通讯的桥梁,以便各类信息的发送与接收。在这个软件中可以与陌生用户或者你已加入用户列表中的用户进行信息的传递来完成基本的交流,系统在后续中是会继续进行功能的完善与拓展,来实现文件传输,语音传输等各种方式来加强用户的体验,为用户带来极大的便利。

    目前即时通讯系统的实现,为了资源的节约,是模仿过其他聊天软件的,在本系统中主要组成部分包含:账号的申请与通过账号进入聊天界面,陌生人到好友的添加,已加好友的删除,好友与好友,与陌生人的信息传递,这些简单易用的小功能确给用户带来了极大的便利,和优秀的用户体验,从而造就一个实用的软件。

    该即时通讯系统可以在很大程度上确保信息的快速性与准确性,而且各种来往的信息传递,都将被存入相关的文件中,以便对其进行相应的管理与维护,在信息发生疏漏与不可避免的一些错误是,进行后期的维护与纠正是极为便利的,是很任性化,所以系统的整体体验是比较优秀的。

    软件已经完成即时聊天系统的基本功能,但是却不是很完善,界面在制作过程中花费不少精力,但仍旧不是很美观,所以在后续仍可以对其进行大量的优化,使其趋于完善,在开发本软件时,发现很多的知识已经比较模糊,所以在这个过程中又将以往所学重温一遍,深感收货颇丰。在开发过程中发现自己并不能很好将以往所学的各种知识融入到其中,所以在后续的学习过程中,还必须多多实践。

    下载地址:

    https://download.csdn.net/download/weixin_41937552/14035843

    展开全文
  • 关于java博网即时通讯软件的设计与实现 Server方面: 1 运行监控,打开Server,执行对其它用户的监控。 2 关闭监控,关闭Server,不在对其它用户进行监控。 3 阅览用户信息,阅览已登录用户信息。 4 ...
  • HTML5和java模仿QQ 实现即时通讯
  • @Resource //这个接口需要手动实现顺序消费的逻辑 每次获取到消息队列的第一条数据 private MessageListenerHandler messageListenerConcurrently; @Bean @ConditionalOnMissingBean public ...

    项目背景

    和各位读者大致介绍下具体场景,线上的小程序中开放一些语音麦克风的房间,让用户进入房间之后可以互相通过语音聊天的方式进行互动。

    这里分享一下相关的技术设计方案。这款系统的核心点设计在于如何能让一个用户发出的语音通知到其他用户上边。语音数据在客户端同事的处理下最终变成了io数据流请求到了后端,后端只需要将这些数据流传达给各个不同的终端即可达到广播通知的效果。

    单机版架构

    最初期上线的时候,为了赶速度,快速试错,所以简单地采用了单机版架构去设计。结合技术栈为 SpringBoot,WebSocket,MySQL技术。

    线上一间语音房间的同时在线人数并不会特别多,大概在15-50人的区间段内,系统核心代码是通过SpringBoot内部的WebSocket技术去进行数据的主动推送。

    设计思路

    整体的设计图比较简单,基本就是一台服务器存储WebSocket连接,如下图所示:

    用户进行WebSocket初始化连接的时候需要一个连接分配和存储的过程:早期的存储是存放在了服务器本地的一个Map集合中。当WebSocket进行连接的时候就会往内存中写入一条数据信息,当链接断开的时候,就将内存中的数据移除。然后进行语音广播的时候需要结合WebSocket内部的广播发送功能进行通知看似设计比较简单,但是在后期业务变得庞大的时候出现了瓶颈。因为随着参加语音活动用户的增加,越来越多的WebSocketSession对象需要被存储到内存当中,这种有状态性的存储对于单机扩容不灵活。

    设计缺陷

    1.假设原先的服务器扩容到了A,B两台机器,A用户在A机器上边建立了WebSocketSession,B用户在B机器上边建立的WebSocketSession连接。此时如果A想要和B进行对话发送,需要先查找到具体WebSocketSession存放在哪台机器上边。

    2.当用户出现了网络异常,临时断开连接进行重连的时候,也可能会出现1所说的问题。

    集群架构

    设计思路

    一旦出现需要发送语音通知的时候,发送一条广播的mq消息,每个机器都接收到消息之后,触发自己的广播操作即可。

    RocketMq的接入系统设计里面mq采用的是广播模式,这和我们通常使用的集群模式有一定的区别。

    消息队列RocketMQ版是基于发布或订阅模型的消息系统。消费者,即消息的订阅方订阅关注的Topic,以获取并消费消息。由于消费者应用一般是分布式系统,以集群方式部署,因此消息队列RocketMQ版约定以下概念:

    • 集群:使用相同Group ID的消费者属于同一个集群。同一个集群下的消费者消费逻辑必须完全一致(包括Tag的使用)。

    • 集群消费:当使用集群消费模式时,消息队列RocketMQ版认为任意一条消息只需要被集群内的任意一个消费者处理即可。

    • 广播消费:当使用广播消费模式时,消息队列RocketMQ版会将每条消息推送给集群内所有注册过的消费者,保证消息至少被每个消费者消费一次。

    集群消费模式适用场景 适用于消费端集群化部署,每条消息只需要被处理一次的场景。此外,由于消费进度在服务端维护,可靠性更高。具体消费示例如下图所示。

    注意事项

    • 集群消费模式下,每一条消息都只会被分发到一台机器上处理。如果需要被集群下的每一台机器都处理,请使用广播模式。

    • 集群消费模式下,不保证每一次失败重投的消息路由到同一台机器上。

    广播消费模式适用场景 适用于消费端集群化部署,每条消息需要被集群下的每个消费者处理的场景。具体消费示例如下图所示。注意事项

    • 广播消费模式下不支持顺序消息。

    • 广播消费模式下不支持重置消费位点。

    • 每条消息都需要被相同订阅逻辑的多台机器处理。

    • 消费进度在客户端维护,出现重复消费的概率稍大于集群模式。

    • 广播模式下,消息队列RocketMQ版保证每条消息至少被每台客户端消费一次,但是并不会重投消费失败的消息,因此业务方需要关注消费失败的情况。

    • 广播模式下,客户端每一次重启都会从最新消息消费。客户端在被停止期间发送至服务端的消息将会被自动跳过,请谨慎选择。

    • 广播模式下,每条消息都会被大量的客户端重复处理,因此推荐尽可能使用集群模式。

    • 广播模式下服务端不维护消费进度,所以消息队列RocketMQ版控制台不支持消息堆积查询、消息堆积报警和订阅关系查询功能。

    这里面的应用场景需要对集群内部对每个消费者都对服务器内存中的socket连接进行session是否存在对判断,因此需要采用mq的广播模式。

    关于mq部分的接入代码

    Consumer模块的配置:

    package org.idea.web.socket.config;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    /**
     * @Author linhao
     * @Date created in 10:30 上午 2021/5/10
     */
    @ConfigurationProperties(prefix = "rocketmq.consumer")
    public class MqConsumerConfig {
        private boolean isOn;
        private String groupName;
        private String nameSrvAddr;
        private String topics;
        private Integer consumeThreadMin;
        private Integer consumeThreadMax;
        private Integer consumeMessageBatchMaxSize;
        
        /**
         getter 和 setter部分省略
        **/
    }
    
    

    Producer模块的配置展示:

    
    package org.idea.web.socket.config;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    /**
     * @Author linhao
     * @Date created in 10:26 上午 2021/5/10
     */
    @ConfigurationProperties(prefix = "rocketmq.producer")
    public class MqProducerConfig {
        private boolean isOn;
        private String groupName;
        private String nameSrvAddr;
        private Integer maxMessageSize;
        private Integer sendMsgTimeout;
        private Integer retryTimesWhenSendFailed;
        
        /**
         getter 和 setter部分省略
        **/
    }
    

    RocketMq内部的消费端Bean配置

    
    package org.idea.web.socket.mq;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
    import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
    import org.apache.rocketmq.client.exception.MQClientException;
    import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
    import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
    import org.idea.web.socket.config.MqConsumerConfig;
    import org.idea.web.socket.config.MqProducerConfig;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import javax.annotation.Resource;
    /**
     * @Author linhao
     * @Date created in 10:34 上午 2021/5/10
     */
    @Configuration
    @Slf4j
    @EnableConfigurationProperties({MqConsumerConfig.class})
    public class MqConsumerAutoConfig {
        @Resource
        private MqConsumerConfig mqConsumerConfig;
        @Resource
        //这个接口需要手动实现顺序消费的逻辑 每次获取到消息队列的第一条数据
        private MessageListenerHandler messageListenerConcurrently;
        @Bean
        @ConditionalOnMissingBean
        public DefaultMQPushConsumer defaultMQPushConsumer() {
            DefaultMQPushConsumer consumer = new DefaultMQPushConsumer();
            consumer.setNamesrvAddr(mqConsumerConfig.getNameSrvAddr());
            consumer.setConsumerGroup(mqConsumerConfig.getGroupName());
            consumer.setConsumeThreadMin(mqConsumerConfig.getConsumeThreadMin());
            consumer.setConsumeThreadMax(mqConsumerConfig.getConsumeThreadMax());
            consumer.registerMessageListener(messageListenerConcurrently);
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            //消费模型是什么?
            consumer.setMessageModel(MessageModel.BROADCASTING);
            //默认一次拉取一条消费
            consumer.setConsumeMessageBatchMaxSize(mqConsumerConfig.getConsumeMessageBatchMaxSize());
            //*表示订阅所有的tag
            try {
                consumer.subscribe(mqConsumerConfig.getTopics(), "*");
                consumer.start();
                log.info("【 MqConsumerAutoConfig 】mq consumer is started!");
            } catch (Exception e) {
                log.error("mq start fail,e is ", e);
            }
            return consumer;
        }
    }
    
    

    RocketMq的服务生产者Bean配置

    package org.idea.web.socket.mq;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.rocketmq.client.producer.DefaultMQProducer;
    import org.idea.web.socket.config.MqProducerConfig;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import javax.annotation.Resource;
    /**
     * @Author linhao
     * @Date created in 11:05 上午 2021/5/10
     */
    @Configuration
    @Slf4j
    @EnableConfigurationProperties({MqProducerConfig.class})
    public class MqProducerAutoConfig {
        @Resource
        private MqProducerConfig mqProducerConfig;
        @Bean
        @ConditionalOnMissingBean
        //意味着DefaultMQProducer的配置可以被覆盖
        public DefaultMQProducer defaultMQProducer() {
            DefaultMQProducer producer = new DefaultMQProducer(mqProducerConfig.getGroupName());
            producer.setNamesrvAddr(mqProducerConfig.getNameSrvAddr());
            //没有则自动创建topic的key
    //        producer.setCreateTopicKey("AUTO_CREATE_TOPIC_KEY");
            producer.setMaxMessageSize(mqProducerConfig.getMaxMessageSize());
            producer.setSendMsgTimeout(mqProducerConfig.getSendMsgTimeout());
            producer.setRetryTimesWhenSendFailed(mqProducerConfig.getRetryTimesWhenSendFailed());
            try {
                producer.start();
                log.info("【 MqProducerAutoConfig 】mq producer is started!");
            } catch (Exception e) {
                log.error("[MqProducerAutoConfig] start fail, e is ", e);
            }
            return producer;
        }
    }
    

    然后是对RocketMq内部发送消息事件的一层函数封装

    package org.idea.web.socket.mq;
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.rocketmq.client.producer.DefaultMQProducer;
    import org.apache.rocketmq.client.producer.SendResult;
    import org.apache.rocketmq.common.message.Message;
    import org.apache.rocketmq.remoting.common.RemotingHelper;
    import org.idea.web.socket.config.MqProducerConfig;
    import org.idea.web.socket.dto.BroadcastMqDTO;
    import org.springframework.stereotype.Component;
    import javax.annotation.Resource;
    import java.io.UnsupportedEncodingException;
    /**
     * 消息广播发送端
     *
     * @Author linhao
     * @Date created in 10:43 下午 2021/5/9
     */
    @Component
    @Slf4j
    public class BroadcastMqProducer {
        @Resource
        private DefaultMQProducer defaultMQProducer;
        @Resource
        private MqProducerConfig mqProducerConfig;
        private static String TOPIC = "ws-topic";
        private static String TAGS = "ws-tag";
    
        public static Integer ALL_USER_RECEIVE_TYPE = 1;
        public static Integer ONE_USER_RECEIVE_TYPE = 2;
        /**
         * 点对点之间的消息发送
         *
         * @param destSessionKey
         * @param msg
         * @return
         */
        public SendResult sendWebSocketToUser(String destSessionKey,String msg) {
            if (StringUtils.isEmpty(msg)) {
                log.error("[sendWebSocketToUser] msg can not be null!");
                return null;
            }
            Message message = null;
            SendResult sendResult = null;
            try {
                BroadcastMqDTO broadcastMqDTO = new BroadcastMqDTO();
                broadcastMqDTO.setEventType(ONE_USER_RECEIVE_TYPE);
                broadcastMqDTO.setMessage(msg);
                broadcastMqDTO.setSessionKey(destSessionKey);
                message = new Message(TOPIC, TAGS, (JSON.toJSONString(broadcastMqDTO)).getBytes(RemotingHelper.DEFAULT_CHARSET));
                sendResult = defaultMQProducer.send(message);
            } catch (Exception e) {
                log.error("[sendWebSocketBroadcastMsg] e is ", e);
            }
            return sendResult;
        }
        /**
         * 广播消息发送
         *
         * @param msg
         * @return
         */
        public SendResult sendWebSocketBroadcastMsg(String msg) {
            if (StringUtils.isEmpty(msg)) {
                log.error("[sendWebSocketBroadcastMsg] msg can not be null!");
                return null;
            }
            Message message = null;
            SendResult sendResult = null;
            try {
                BroadcastMqDTO broadcastMqDTO = new BroadcastMqDTO();
                broadcastMqDTO.setEventType(ALL_USER_RECEIVE_TYPE);
                broadcastMqDTO.setMessage(msg);
                message = new Message(TOPIC, TAGS, (JSON.toJSONString(broadcastMqDTO)).getBytes(RemotingHelper.DEFAULT_CHARSET));
                sendResult = defaultMQProducer.send(message);
            } catch (Exception e) {
                log.error("[sendWebSocketBroadcastMsg] e is ", e);
            }
            return sendResult;
        }
    }
    
    

    对消息的订阅模块实现代码如下:

    package org.idea.web.socket.mq;
    import com.alibaba.fastjson.JSON;
    import com.oracle.tools.packager.Log;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
    import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
    import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
    import org.apache.rocketmq.common.message.MessageExt;
    import org.idea.web.socket.dto.BroadcastMqDTO;
    import org.idea.web.socket.manager.SocketManager;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    import org.springframework.web.socket.WebSocketSession;
    import javax.annotation.Resource;
    import java.util.List;
    import static org.idea.web.socket.mq.BroadcastMqProducer.ALL_USER_RECEIVE_TYPE;
    import static org.idea.web.socket.mq.BroadcastMqProducer.ONE_USER_RECEIVE_TYPE;
    /**
     * @Author linhao
     * @Date created in 10:59 上午 2021/5/10
     */
    @Component
    @Slf4j
    public class MessageListenerHandler implements MessageListenerConcurrently {
        @Resource
        private SocketManager socketManager;
        @Resource
        private SimpMessagingTemplate template;
        @Override
        public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
            if (CollectionUtils.isEmpty(list)) {
                Log.info("receive empty msg");
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
            MessageExt messageExt = list.get(0);
            byte[] bytes = messageExt.getBody();
            String json = new String(bytes);
            BroadcastMqDTO broadcastMqDTO = JSON.parseObject(json, BroadcastMqDTO.class);
            log.info("[MessageListenerHandler] broadcastMqDTO is " + broadcastMqDTO);
            if (ALL_USER_RECEIVE_TYPE.equals(broadcastMqDTO.getEventType())) {
                log.info("[consumeMessage] 广播发送消息:触发----》消息内容为:" + broadcastMqDTO);
                template.convertAndSend("/topic/sendTopic", broadcastMqDTO);
            } else if (ONE_USER_RECEIVE_TYPE.equals(broadcastMqDTO.getEventType())) {
                String sessionKey = broadcastMqDTO.getSessionKey();
                WebSocketSession webSocketSession = socketManager.get(sessionKey);
                if (webSocketSession != null) {
                    template.convertAndSendToUser(sessionKey, "/queue/sendUser", broadcastMqDTO.getMessage());
                    log.info("[consumeMessage] 点对点发送消息;触发----》消息内容为:" + broadcastMqDTO);
                }
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        }
    }
    
    
    

    整体设计结构如下图:

    于是按照这个结构进行了一版本的紧急开发迭代,原先的单台服务器扩展为了服务集群。

    业务拓展后续产品经理提出一个需求,要求支持在同一间房内的两个用户之间发送悄悄话功能。这就需要我们进行一个点对点之间传输通讯的功能了。因此需要在mq通知到每台机器的时候加一个本地Session遍历的逻辑,如果当前机器存有用户token对应的session变量,那么就单独针对那个Session进行WebSocket的发送通知。设计弊端一旦某台机器出现了异常崩溃,那么就意味着这台机器上的所有语音连接可能会出现中断情况。目前这一块的问题也在考虑解决,计划是将WebSocketSession存入到分布式缓存的redis中保证数据可靠存储,但是在后续尝试的时候发现WebSocketSession对象没有实现序列化接口,在存储到Redis的时候会出现异常。目前这个问题还在寻找解决思路中,不知道各位读者朋友们有什么好的思路。

    遇到的问题点用户请求直接访问到了我们的内部服务器,如果在请求的中间加入一台nginx做负载均衡则需要在nginx中配置一些额外信息。

    项目的源代码比较多,这里我把核心部分的代码整理了一份,感兴趣的朋友可以到我的gitee上边去下载:

    https://gitee.com/IdeaHome_admin/socket-framework

    推荐好文

    >>【练手项目】基于SpringBoot的ERP系统,自带进销存+财务+生产功能>>分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!
    >>能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!
    
    
    
    
    展开全文
  • java实现即时通信的完整步骤分享

    千次阅读 2021-02-12 09:30:24
    前言移动社交是我们日常生活中很常见的软件,最近在做即时通信,我用的是环信,和大家分享一下~~环信的API都是基于JSON的,所以在构造HTTP请求的时候,要指定请求头:注意==》环信API必须携带token才可以访问。...

    前言

    移动社交是我们日常生活中很常见的软件,最近在做即时通信,我用的是环信,和大家分享一下~~

    环信的API都是基于JSON的,所以在构造HTTP请求的时候,要指定请求头:

    e27382a1cf0ca8e9464af9e55fb96563.png

    bb7ce353325ebf17e002facb2abdc195.png

    注意==》环信API必须携带token才可以访问。

    创建一个认证类

    public class Authentic {

    private static Token token = new Token();

    private TalkHttpService service;

    public Authentic(TalkHttpService service) {

    this.service = service;

    }

    public Authentic(TalkHttpService service, Token token) {

    this.service = service;

    if (token != null) {

    Authentic.token = token;

    }

    }

    public Token getToken() {

    this.flush();

    return token;

    }

    public void task() {

    this.flush();

    }

    /**

    * @describe 申请认证 POST PUT 这两种请求携带参数

    * @author 何章怀晓 hezhanghuaixiao

    * @date 2020/9/8 17:02

    * @other

    */

    public void applyAuthentication(HttpEntityEnclosingRequestBase request) {

    this.flush();

    request.addHeader("Authorization", "Bearer " + token.toString());

    }

    /**

    * @describe 申请认证 GET DELETE 这两种请求不携带参数

    * @author 何章怀晓 hezhanghuaixiao

    * @date 2020/9/8 17:02

    * @other

    */

    public void applyAuthentication(HttpRequestBase request) {

    this.flush();

    request.addHeader("Authorization", "Bearer " + token.toString());

    }

    private void flush() {

    synchronized (Authentic.class) {

    try {

    //如果超时

    if (token.isExpire()) {

    //判断APPID和秘钥信息

    if (_Global.APP_CLIENT_ID != null && _Global.APP_CLIENT_SECRET != null) {

    Map param = new HashMap();

    param.put("grant_type", "client_credentials");

    param.put("client_id", _Global.APP_CLIENT_ID);

    param.put("client_secret", _Global.APP_CLIENT_SECRET);

    //请求获取token

    TalkNode res = service

    .request(_Global.URR_TOKEN, _Global.HTTP_METHOD_POST, param, null, null);

    //成功获取token

    if (res != null && res.getAccess_token() != null && res.getExpires_in() != null

    && res.getExpires_in() > 0) {

    //赋值

    token = new Token(res.getAccess_token(),

    res.getExpires_in() * 1000 + System.currentTimeMillis());

    }

    }

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    public static class Token {

    private String token;

    private Long expire;

    public Token() {

    }

    public Token(String token, long expire) {

    this.token = token;

    this.expire = expire;

    }

    public String getToken() {

    return token;

    }

    public void setToken(String token) {

    this.token = token;

    }

    public Long getExpire() {

    return expire;

    }

    public void setExpire(Long expire) {

    this.expire = expire;

    }

    public boolean isExpire() {

    return expire == null || System.currentTimeMillis() > expire;

    }

    @Override

    public String toString() {

    return token;

    }

    }

    }

    创建请求接口

    public interface TalkHttpService {

    /**

    @describe

    @param

    * @param url 请求地址

    * @param method请求方法

    * @param param参数

    * @param auth加密认证

    * @param field字段转换

    @return com.hedashi.protal.model.TalkNode

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:21

    @other

    */

    TalkNode request(String url, int method, Object param,

    Authentic auth, String[][] field) throws Exception;

    /**

    @describe

    @param

    * @param url 请求地址

    * @param file文件名称

    * @param auth加密认证

    * @param equal字段转换

    @return com.hedashi.protal.model.TalkNode

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:21

    @other

    */

    TalkNode upload(String url, File file, Authentic auth,

    String[][] equal) throws Exception;

    /**

    @describe

    @param

    * @param url 请求地址

    * @param file文件名称

    * @param auth加密认证

    * @param header请求头

    @return void

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:21

    @other

    */

    void downLoad(String url, File file, Authentic auth,

    Map header) throws Exception;

    }

    创建全局变量对不同模块操作

    /*

    @describe 全局变量

    @params

    @return

    @author 何章怀晓

    @date 2020/7/30 9:30

    @other

    */

    public class _Global {

    public static String APP_KEY = "";

    public static String APP_CLIENT_ID = "";

    public static String APP_CLIENT_SECRET = "";

    //每页数量

    public static int APP_PAGE_SIZE = 10;

    public static final int HTTP_METHOD_GET = 1;

    public static final int HTTP_METHOD_POST = 2;

    public static final int HTTP_METHOD_PUT = 3;

    public static final int HTTP_METHOD_DELETE = 4;

    public static final String URL_HOST = "http://a1.easemob.com/"+APP_KEY.replace("#","/")+"/";

    public static final String URR_TOKEN = URL_HOST+"token";

    public static final String URL_CHAT = URL_HOST+"chatmessages";

    public static final String URL_GROUP = URL_HOST+"chatgroups";

    public static final String URL_FILE = URL_HOST+"chatfiles";

    public static final String URL_ROOM = URL_HOST+"chatrooms";

    public static final String URL_MESSAGES = URL_HOST+"messages";

    public static final String URL_USER = URL_HOST+"users";

    }

    请求管理类

    package com.hedashi.protal.service.impl;

    import com.hedashi.protal.model.TalkNode;

    import com.hedashi.protal.model.Authentic;

    import com.hedashi.protal.service.TalkHttpService;

    import com.hedashi.protal.util.JsonTool;

    import com.hedashi.protal.util._Global;

    import java.io.File;

    import java.io.FileOutputStream;

    import java.io.InputStream;

    import java.net.URI;

    import java.util.Map;

    import java.util.Map.Entry;

    import org.apache.http.HttpEntity;

    import org.apache.http.HttpResponse;

    import org.apache.http.HttpStatus;

    import org.apache.http.client.methods.HttpDelete;

    import org.apache.http.client.methods.HttpGet;

    import org.apache.http.client.methods.HttpPost;

    import org.apache.http.client.methods.HttpPut;

    import org.apache.http.entity.StringEntity;

    import org.apache.http.entity.mime.MultipartEntity;

    import org.apache.http.entity.mime.content.ContentBody;

    import org.apache.http.entity.mime.content.FileBody;

    import org.apache.http.impl.client.CloseableHttpClient;

    import org.apache.http.impl.client.HttpClients;

    import org.apache.http.util.EntityUtils;

    import org.springframework.stereotype.Service;

    @Service

    public class TalkHttpServiceImplApache implements TalkHttpService {

    /**

    @describe

    @param

    * @param url 请求路径

    * @param method 方式

    * @param param 参数

    * @param auth 认证

    * @param field 将相应结果封装到本地

    @return com.hedashi.protal.model.TalkNode

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:39

    @other

    */

    @Override

    public TalkNode request(String url, int method, Object param,

    Authentic auth, String[][] field) throws Exception {

    //获得可关闭的连接

    CloseableHttpClient client = this.getClient();

    try {

    HttpResponse response = null;

    //区分请求方式

    switch (method) {

    case _Global.HTTP_METHOD_GET:

    //构建请求

    HttpGet get = new HttpGet(url);

    if (auth != null) {

    //如果未认证 请求认证

    auth.applyAuthentication(get);

    }

    //固定请求头信息为JSON

    get.addHeader("Content-Type", "application/json");

    response = client.execute(get);

    break;

    case _Global.HTTP_METHOD_POST:

    HttpPost post = new HttpPost(url);

    if (auth != null) {

    auth.applyAuthentication(post);

    }

    //POST携带参数

    if (param != null) {

    //参数编码放入请求体

    post.setEntity(new StringEntity(JsonTool.write(param),

    "UTF-8"));

    }

    post.addHeader("Content-Type", "application/json");

    response = client.execute(post);

    break;

    case _Global.HTTP_METHOD_PUT:

    HttpPut put = new HttpPut(url);

    if (put != null) {

    auth.applyAuthentication(put);

    }

    if (param != null) {

    put.setEntity(new StringEntity(JsonTool.write(param),

    "UTF-8"));

    }

    put.addHeader("Content-Type", "application/json");

    response = client.execute(put);

    break;

    case _Global.HTTP_METHOD_DELETE:

    HttpDelete delete = new HttpDelete(url);

    if (auth != null) {

    auth.applyAuthentication(delete);

    }

    delete.addHeader("Content-Type", "application/json");

    response = client.execute(delete);

    break;

    default:

    throw new Exception("非法请求方式");

    }

    int code = response.getStatusLine().getStatusCode();

    //判断返回code 如果为200

    if (code == HttpStatus.SC_OK) {

    //获取响应体

    HttpEntity entity = response.getEntity();

    if (entity != null) {

    //解析

    String json = EntityUtils.toString(entity, "UTF-8");

    if (field != null && field.length > 0) {

    for (String[] temp : field) {

    json = json.replace(temp[0], temp[1]);

    }

    }

    //解析为实体类

    TalkNode talkNode = (TalkNode) JsonTool.read(json, TalkNode.class);

    talkNode.setStatusCode(code);

    return talkNode;

    }

    } else {

    //非200将code返回

    return new TalkNode(code);

    }

    } catch (Exception e) {

    throw e;

    } finally {

    client.close();

    }

    return null;

    }

    @Override

    public TalkNode upload(String url, File file, Authentic auth,

    String[][] equal) throws Exception {

    CloseableHttpClient client = this.getClient();

    try {

    HttpPost post = new HttpPost();

    post.setURI(new URI(url));

    if (auth != null) {

    auth.applyAuthentication(post);

    }

    post.addHeader("restrict-access", "true");

    ContentBody body = new FileBody(file);

    MultipartEntity part = new MultipartEntity();

    part.addPart("file", body);

    post.setEntity(part);

    HttpResponse response = client.execute(post);

    int code = response.getStatusLine().getStatusCode();

    if (code == HttpStatus.SC_OK) {

    HttpEntity entity = response.getEntity();

    if (entity != null) {

    String json = EntityUtils.toString(entity, "UTF-8");

    if (equal != null && equal.length > 0) {

    for (String[] temp : equal) {

    json = json.replace(temp[0], temp[1]);

    }

    }

    TalkNode talkNode = (TalkNode) JsonTool.read(json, TalkNode.class);

    talkNode.setStatusCode(code);

    return talkNode;

    }

    }

    } catch (Exception e) {

    throw e;

    } finally {

    client.close();

    }

    return null;

    }

    @Override

    public void downLoad(String url, File file, Authentic auth,

    Map header) throws Exception {

    CloseableHttpClient client = this.getClient();

    try {

    HttpGet get = new HttpGet();

    get.setURI(new URI(url));

    if (auth != null) {

    auth.applyAuthentication(get);

    }

    for (Entry en : header.entrySet()) {

    get.addHeader(en.getKey(), en.getValue());

    }

    HttpResponse response = client.execute(get);

    if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

    HttpEntity entity = response.getEntity();

    if (entity != null) {

    InputStream in = entity.getContent();

    FileOutputStream fos = new FileOutputStream(file);

    byte[] data = new byte[10 * 1024];

    int len = 0;

    while ((len = in.read(data)) != -1) {

    fos.write(data, 0, len);

    }

    fos.flush();

    fos.close();

    in.close();

    }

    }

    } catch (Exception e) {

    throw e;

    } finally {

    client.close();

    }

    }

    private CloseableHttpClient getClient() {

    return HttpClients.createDefault();

    }

    }

    创建业务请求和响应格式类

    package com.hedashi.protal.model;

    import java.util.List;

    import java.util.Map;

    /**

    @describe 根据不同的业务封装不同的返回结果,该格式在发送请求的时候就被指定

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:42

    @other

    */

    public class TalkNode {

    public static final String[][] DATA_ENTITIES = new String[][]{{"entities", "entities_share"},

    {"share-secret", "share_secret"}};

    public static final String[][] DATA_ARRAY = new String[][]{{"data", "data_array"}};

    public static final String[][] DATA_LIST = new String[][]{{"data", "data_list"}};

    public static final String[][] DATA_MAP = new String[][]{{"data", "data_map"}};

    public static final String[][] DATA_CHAT_LIST = new String[][]{{"entities", "data_chat_list"}};

    public static final String[][] DATA_ROOM = new String[][]{{"data", "data_room"}};

    public static final String[][] DATA_ROOM_LIST = new String[][]{{"data", "data_room_list"},

    {"public", "public_room"}};

    public static final String[][] DATA_ROOM_REDO = new String[][]{{"data", "data_room_rodo"}};

    public static final String[][] DATA_ROOM_REDO_LIST = new String[][]{

    {"data", "data_room_redo_list"}};

    public static final String[][] DATA_GROUP = new String[][]{{"data", "data_group"}};

    public static final String[][] DATA_GROUP_UPDATE = new String[][]{{"data", "data_group_update"}};

    public static final String[][] DATA_GROUP_OWNER = new String[][]{{"data", "data_group_owner"}};

    public static final String[][] DATA_GROUP_LIST = new String[][]{{"data", "data_group_list"}};

    public static final String[][] DATA_GROUP_LIST_MEMBER = new String[][]{

    {"data", "data_group_list_member"}};

    public static final String[][] DATA_GROUP_LIST_NEW = new String[][]{

    {"data", "data_group_list_new"}, {"public", "public_group"}};

    public static final String[][] DATA_GROUP_FRIEND = new String[][]{{"data", "data_group_friend"}};

    public static final String[][] DATA_GROUP_FRIEND_LIST = new String[][]{

    {"data", "data_group_friend_list"}};

    private String access_token;

    private String action;

    private String application;

    private String applicationName;

    private Long count;

    private String cursor;

    private Integer duration;

    private Long expires_in;

    private String organization;

    private String path;

    private Integer statusCode;

    private Long timestamp;

    private String uri;

    private Map params;

    private TalkUser user;

    private List entities;

    private String[] data_array;

    private Map data_map;

    private List> data_list;

    private List data_chat_list;

    private TalkRoom data_room;

    private List data_room_list;

    private TalkRoomRedo data_room_rodo;

    private List data_room_redo_list;

    private TalkGroup data_group;

    private TalkGroupMember data_group_update;

    private TalkGroupMember data_group_owner;

    private List data_group_list;

    private List data_group_list_member;

    private List data_group_list_new;

    private TalkGroupFriend data_group_friend;

    private List data_group_friend_list;

    public TalkNode() {

    }

    public TalkNode(Integer statusCode) {

    this.statusCode = statusCode;

    }

    public String getAccess_token() {

    return access_token;

    }

    public void setAccess_token(String access_token) {

    this.access_token = access_token;

    }

    public String getAction() {

    return action;

    }

    public void setAction(String action) {

    this.action = action;

    }

    public String getApplication() {

    return application;

    }

    public void setApplication(String application) {

    this.application = application;

    }

    public String getApplicationName() {

    return applicationName;

    }

    public void setApplicationName(String applicationName) {

    this.applicationName = applicationName;

    }

    public Long getCount() {

    return count;

    }

    public void setCount(Long count) {

    this.count = count;

    }

    public String getCursor() {

    return cursor;

    }

    public void setCursor(String cursor) {

    this.cursor = cursor;

    }

    public Integer getDuration() {

    return duration;

    }

    public void setDuration(Integer duration) {

    this.duration = duration;

    }

    public Long getExpires_in() {

    return expires_in;

    }

    public void setExpires_in(Long expires_in) {

    this.expires_in = expires_in;

    }

    public String getOrganization() {

    return organization;

    }

    public void setOrganization(String organization) {

    this.organization = organization;

    }

    public String getPath() {

    return path;

    }

    public void setPath(String path) {

    this.path = path;

    }

    public Integer getStatusCode() {

    return statusCode;

    }

    public void setStatusCode(Integer statusCode) {

    this.statusCode = statusCode;

    }

    public Long getTimestamp() {

    return timestamp;

    }

    public void setTimestamp(Long timestamp) {

    this.timestamp = timestamp;

    }

    public String getUri() {

    return uri;

    }

    public void setUri(String uri) {

    this.uri = uri;

    }

    public Map getParams() {

    return params;

    }

    public void setParams(Map params) {

    this.params = params;

    }

    public TalkUser getUser() {

    return user;

    }

    public void setUser(TalkUser user) {

    this.user = user;

    }

    public List getEntities() {

    return entities;

    }

    public void setEntities(List entities) {

    this.entities = entities;

    }

    public String[] getData_array() {

    return data_array;

    }

    public void setData_array(String[] data_array) {

    this.data_array = data_array;

    }

    public Map getData_map() {

    return data_map;

    }

    public void setData_map(Map data_map) {

    this.data_map = data_map;

    }

    public List> getData_list() {

    return data_list;

    }

    public void setData_list(List> data_list) {

    this.data_list = data_list;

    }

    public List getData_chat_list() {

    return data_chat_list;

    }

    public void setData_chat_list(List data_chat_list) {

    this.data_chat_list = data_chat_list;

    }

    public TalkRoom getData_room() {

    return data_room;

    }

    public void setData_room(TalkRoom data_room) {

    this.data_room = data_room;

    }

    public List getData_room_list() {

    return data_room_list;

    }

    public void setData_room_list(List data_room_list) {

    this.data_room_list = data_room_list;

    }

    public TalkRoomRedo getData_room_rodo() {

    return data_room_rodo;

    }

    public void setData_room_rodo(TalkRoomRedo data_room_rodo) {

    this.data_room_rodo = data_room_rodo;

    }

    public List getData_room_redo_list() {

    return data_room_redo_list;

    }

    public void setData_room_redo_list(List data_room_redo_list) {

    this.data_room_redo_list = data_room_redo_list;

    }

    public TalkGroup getData_group() {

    return data_group;

    }

    public void setData_group(TalkGroup data_group) {

    this.data_group = data_group;

    }

    public TalkGroupMember getData_group_update() {

    return data_group_update;

    }

    public void setData_group_update(TalkGroupMember data_group_update) {

    this.data_group_update = data_group_update;

    }

    public TalkGroupMember getData_group_owner() {

    return data_group_owner;

    }

    public void setData_group_owner(TalkGroupMember data_group_owner) {

    this.data_group_owner = data_group_owner;

    }

    public List getData_group_list() {

    return data_group_list;

    }

    public void setData_group_list(List data_group_list) {

    this.data_group_list = data_group_list;

    }

    public List getData_group_list_member() {

    return data_group_list_member;

    }

    public void setData_group_list_member(

    List data_group_list_member) {

    this.data_group_list_member = data_group_list_member;

    }

    public List getData_group_list_new() {

    return data_group_list_new;

    }

    public void setData_group_list_new(List data_group_list_new) {

    this.data_group_list_new = data_group_list_new;

    }

    public TalkGroupFriend getData_group_friend() {

    return data_group_friend;

    }

    public void setData_group_friend(TalkGroupFriend data_group_friend) {

    this.data_group_friend = data_group_friend;

    }

    public List getData_group_friend_list() {

    return data_group_friend_list;

    }

    public void setData_group_friend_list(

    List data_group_friend_list) {

    this.data_group_friend_list = data_group_friend_list;

    }

    }

    工具类

    public class HuanXinUtil {

    private static TalkDataService service = null;

    /**

    @describe 初始化

    @param

    * @param

    @return void

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:26

    @other

    */

    private static void init(){

    if(service == null){

    // 初始服务端Token

    Authentic.Token token = new Authentic(new TalkHttpServiceImplApache()).getToken();

    //token和过期时间

    Authentic.Token TEST_TOKEN = new Authentic.Token(token.getToken(),token.getExpire());

    //新建一个链接服务

    service = new TalkDataServiceImpl(new TalkHttpServiceImplApache());

    // 修改数据业务Token

    service.setToken(TEST_TOKEN);

    }

    }

    /**

    @describe 添加管理员

    @param

    * @param groupId 群组id

    * @param userid 管理员id

    @return boolean

    @author 何章怀晓 hezhanghuaixiao

    @date 2020/9/8 17:54

    @other

    */

    public static boolean addGroupManager(String groupId,String userid) {

    try {

    init();

    TalkNode talkNode = service.addGroupManager(groupId,userid);

    if(talkNode.getStatusCode()==200){

    return true;

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    return false;

    }

    }

    service调用

    @Override

    public TalkNode addGroupManager(String id, String userId) throws Exception {

    Map param = new HashMap();

    param.put("newadmin", userId);

    return service.request(_Global.URL_GROUP + "/" + id + "/admin",

    _Global.HTTP_METHOD_POST, param, auth, TalkNode.DATA_GROUP);

    }

    /**

    * @param [groupId, managerId]

    * @return com.hedashi.common.api.CommonResult

    * @describe 后台添加群组管理员

    * @author 何章怀晓 hezhanghuaixiao

    * @date 2020/9/8 14:28

    * @other

    */

    @Override

    public CommonResult addGroupManager(String groupId, String managerId) {

    boolean b = HuanXinUtil.addGroupManager(groupId, managerId);

    if(b){

    System.out.println("环信添加管理员成功==========================");

    //本地添加管理员

    addGroupAdmin(groupId,managerId);

    return CommonResult.success("SUCCESS");

    }

    return CommonResult.failed("FAILED");

    }

    @ApiOperation(value = "群组添加管理员")

    @RequestMapping(value = "/addGroupManager", method = RequestMethod.POST)

    @ResponseBody

    public CommonResult addGroupManager(

    @RequestParam @ApiParam(value = "群组环信ID", required = true) String groupId,

    @RequestParam @ApiParam(value = "管理员环信id", required = true) String managerId

    ) {

    return heUGroupService.addGroupManager(groupId,managerId);

    }

    swagger调用

    7c9fcd41c37c7343d4867d1c3bb92186.png

    token 信息

    {“application”:“53e3eeb5-6926-46dd-bc61-4e214342ef7e”,“access_token”:“YWMtXDS-uPG6EeqItFktBQxljAAAAAAAAAAAAAAAAAAAAAFT4-61aSZG3bxhTiFDQu9-AgMAAAF0bSppWwBPGgBXDkgrlvguBLEe966D_LnbgNyNz2OOsTgP4okhQGoOdA”,“expires_in”:5184000}

    swagger返回结果

    34ac25d3ab8d6ddb0a296b9b14424cad.png

    控制台

    2123acad6f76171139f885eca299a336.png

    数据库:

    6c151885adcf320ef833cdceb9ed6170.png

    总结

    到此这篇关于java实现即时通信的文章就介绍到这了,更多相关java实现即时通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    展开全文
  • 序:JSR 356:Java API for WebSocket是javaee7新推出来的一个新的特性,他相对于其它容器实现,优点是他是一个标准.容器的更新都会遵守这个标准.不需要更改代码.减少后期的维护工作量.webscoket主要的作用是用来双向...
  • 基于Java即时通讯软件的设计与实现 一、项目设计 1. 模块设计 该即时通讯系统是有两部分组成, 服务器端可以通过启动来监听客户端信息的传递与执行各种对客户端的监控,客户端则是通过人性化与美观的界面来使...
  • 实现了浏览器与服务器全双工(full-duplex)通信–允许服务器主动发送信息给客户端。 前端代码 实现连接后端,接收发送消息(私发,群发) <!DOCTYPE html> <html lang="en"> <head> <meta ...
  • Java实现的socket即时通讯APP,使用了云数据库,目前数据库过期,无法正常使用,自己配置一下本地的数据库就可以了。数据库配置正常后可以实现两台电脑上的同步通讯。有说明文档和代码包,为小组作业,勿传播,谢谢...
  • java博网即时通讯软件的设计与实现源码包含数据库,下载安装即用。 Server方面: 1 运行监控,打开Server,执行对其它用户的监控。 2 关闭监控,关闭Server,不在对其它用户进行监控。 3 阅览用户信息,阅览已...
  • 基于Java编程语言的内网即时通讯插件系统设计与实现
  • 即时通信系统(Java实现),完整版,可供大家参考学习
  • 使用Java-WebSocket开源框架开发Android端即时通讯功能。目前主要功能:1、与websocket建立长连接2、与websocket进行即时通讯3、Service和Activity之间通讯和UI更新4、弹出消息通知(包括锁屏通知)5、心跳检测和重...
  • 它有着自己的易用特点与性能优势,比如跨平台、安全性、多线程、网络Socket编程、数据流概念等方面,因此通过对开源即时通讯LinuxQQ的研究和分析,基于Java语言和J2EE规范设计了一个即时通讯工具JICQ (Java for I ...
  • 基于Java实现即时通信系统
  • 实时JavaJava语言的一组增强功能,它们为应用程序提供的实时性能要超过标准Java技术。 实时性能与传统的吞吐量性能不同,传统的吞吐量性能通常是对可以在固定时间内完成的指令,任务或工作总数的度量。 实时性能...
  • 本系统使用java开发,使用myeclipse和SqlServer数据库,可以实现用户的即时通讯功能
  • 即时通讯(Instant Messaging)最重要的毫无疑问就是即时,不能有明显的延迟,要实现IM的功能其实并不难,目前有很多第三方,比如极光的JMessage,都比较容易实现。但是如果项目有特殊要求(如不能使用外网),那就...
  • 即时通讯全套JAVA源码

    2019-09-25 15:23:00
    JAVA语言,基于t-io开发的轻量、高性能、单机支持几十万至百万在线用户IM,主要目标降低即时通讯门槛,快速打造低成本接入在线IM系统,通过极简洁的消息格式就可以实现多端不同协议间的消息发送如内置(Http、...
  • 之前工作接触了几个开源的IM产品,再加上曾经用Netty实现过几个服务,于是就有了用Netty实现一个IM的想法,于是用业余时间写了一个IM,和喜欢Netty的程序员们分享。考虑到方便扩展,在服务端采用了Http+Socket结合的...
  • 基于Java实现即时通信系统,很适合刚学Java的人群做简单的Java开发小项目
  • 关于java博网即时通讯软件的设计与实现 Server方面: 1 运行监控,打开Server,执行对其它用户的监控。 2 关闭监控,关闭Server,不在对其它用户进行监控。 3 阅览用户信息,阅览已登录用户信息。 4 管理用户,强制使...
  • 基于Java的网络即时通讯系统的设计与实现,有难度

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,422
精华内容 8,568
关键字:

java实现即时通讯

java 订阅
友情链接: clip and reclass.zip