如果你也在面临做直播的 业务的时候迷茫的时候,来看看吧。

腾讯云–云直播

最近这几个项目也是在做直播相关的App开发,之前刚做的时候,自己也经历很多坑。
慢慢的爬过这些坑,做了几款直播软件以后,也算有了心得。更加熟练的调用。
分享自己的做直播的流程,以及配合腾讯云的直播官方文档的调用。

我做的这几个直播的项目是基于腾讯云的云直播服务进行开发的

  1. 腾讯云的账户分:个人账户和企业认证账户。
  2. 只有认证方式是不同的,其他的操作已经步骤以及思路都是一样的。
  3. 首先: 先去认证账户信息,进行实名认证的流程后,就可以使用腾讯云的服务了。
  4. 新的用户首次认证的时候,都可以免费体验腾讯云的云直播和即时通讯IM的服务(免费试用期一个月)
  5. 下面直接进入开发吧,不多啰嗦。

登录腾讯云的管理后台

  1. 点击云直播。(如果你是第一次使用腾讯云的云直播的话,你是需要去开通云直播服务后,才能可以进行使用)

-----现在看到的就是云直播的后台
1:首先,你要理解,直播是怎么回事?-----回答:直播利用的就是腾讯提供的云直播的服务,推流,拉流,客户端(主播)发起推流,创建直播房间成功后,创建IM群组成功后,客户端(用户)发起拉流。用户进入直播间可以看到主播的直播画面,这就是拉流成功。主播进行开播,开播后,主播可以看到自己的画面,能持续直播并且有画面,说明此时的推流地址是没问题的,可以进行直播。
2:其次就是怎么配置腾讯云的云直播后台的配置 ----回答:核心的配置,就是配置两条已经备案过的域名(一条域名用来做推流域名,另一条域名用来做拉流域名)
3:腾讯云的直播如何集成到自己的代码开发中去 —回答:集成自己的代码开发,这块我会在后面进行详细的讲解,以及代码的示范提供。

参考腾讯云的官方文档配置推拉流域名

新手指南

建议新手区参考新手指南,
先去看看,把直播的这两条推拉流域名配置好。
一条推流域名,一条拉流域名(都是需要去备案的)

其次就是要开通新手免费使用的流量包,没有流量包是不能进行直播的。

接下来需要了解,如何生成推流拉流地址。
先看腾讯云给出的生成规则。
只要你满足生成规则,你生成的流地址是正常的,就可以用来进行推拉流,进行正常的直播。


先看官网的地址生成器:

1:看看需要哪些参数
2:看看地址解析说明的配置
3:推拉流地址是要经过我们后台去代码生成的,然后返回给前端,安卓或者IOS,拿着地址去调用腾讯云的直播SDK,进行推流,拉流,完成APP端的主播,开播,用户进入直播间去观看,等功能。


具体看看,怎么生成推拉流的地址的


在这里,有官网提供的推拉流地址的生成代码


package com.test;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class Test {public static void main(String[] args) {System.out.println(getSafeUrl("txrtmp", "11212122", 1469762325L));}private static final char[] DIGITS_LOWER ={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};/** KEY+ streamName + txTime*/private static String getSafeUrl(String key, String streamName, long txTime) {String input = new StringBuilder().append(key).append(streamName).append(Long.toHexString(txTime).toUpperCase()).toString();String txSecret = null;try {MessageDigest messageDigest = MessageDigest.getInstance("MD5");txSecret  = byteArrayToHexString(messageDigest.digest(input.getBytes("UTF-8")));} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return txSecret == null ? "" :new StringBuilder().append("txSecret=").append(txSecret).append("&").append("txTime=").append(Long.toHexString(txTime).toUpperCase()).toString();}private static String byteArrayToHexString(byte[] data) {char[] out = new char[data.length << 1];for (int i = 0, j = 0; i < data.length; i++) {out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];out[j++] = DIGITS_LOWER[0x0F & data[i]];}return new String(out);}
}

下面是我改进后的代码,大家可以作为参考:

package com.*.utils;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;/*** 推拉流生成工具* @author * @date 2020-10-16 12:11:58*/
public class AutoAddressUtils {private static final char[] DIGITS_LOWER ={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};private static final String pushKey = "f58*********d4f5d"; //域名管理中点击推流域名-->推流配置-->鉴权配置-->主KEYprivate static final String pushDomain = "*********"; //云直播控制台配置的推流域名private static final String pullDomain = "*********";//云直播控制台配置的拉流域名private static final String AppName = "live"; //直播SDK-->应用管理-->自己创建应用中的应用名称public static void main(String[] args) {long LiveRecordId = Long.parseLong(GenerateIdUtil.generateIdUtilId());System.out.println(LiveRecordId);LocalDateTime localDateTime =  LocalDateTime.now();long nowTime = localDateTime.toEpochSecond(ZoneOffset.of("+8"));long endTime = nowTime + 60*60*12;     // 默认12小时LiveAddress addressUrl = AutoAddressUtils.getAddressUrl(GenerateIdUtil.generateIdUtilId(), endTime);System.out.println(addressUrl.getPushRTMP());System.out.println(addressUrl.getPullUDP());System.out.println(addressUrl.getPullRTMP());System.out.println(addressUrl.getPullM3U8());System.out.println(addressUrl.getPullFLV());}public static LiveAddress getAddressUrl(String streamName, long txTime) {String safeUrl = getSafeUrl(pushKey, streamName, txTime);LiveAddress liveAddress = new LiveAddress();liveAddress.setPushRTMP("rtmp://"+pushDomain+"/"+AppName+"/"+streamName+"?"+safeUrl);liveAddress.setPullRTMP("rtmp://"+pullDomain+"/"+AppName+"/"+streamName+"?"+safeUrl);liveAddress.setPullFLV("http://"+pullDomain+"/"+AppName+"/"+streamName+".flv?"+safeUrl);liveAddress.setPullM3U8("http://"+pullDomain+"/"+AppName+"/"+streamName+".m3u8?"+safeUrl);liveAddress.setPullUDP("webrtc://"+pullDomain+"/"+AppName+"/"+streamName+"?"+safeUrl);return liveAddress;}/** KEY+ streamName + txTime*/private static String getSafeUrl(String key, String streamName, long txTime) {String input = new StringBuilder().append(key).append(streamName).append(Long.toHexString(txTime).toUpperCase()).toString();String txSecret = null;try {MessageDigest messageDigest = MessageDigest.getInstance("MD5");txSecret  = byteArrayToHexString(messageDigest.digest(input.getBytes("UTF-8")));} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return txSecret == null ? "" :new StringBuilder().append("txSecret=").append(txSecret).append("&").append("txTime=").append(Long.toHexString(txTime).toUpperCase()).toString();}private static String byteArrayToHexString(byte[] data) {char[] out = new char[data.length << 1];for (int i = 0, j = 0; i < data.length; i++) {out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];out[j++] = DIGITS_LOWER[0x0F & data[i]];}return new String(out);}
}

1:生成推拉流的地址,前端调用云直播的SDK,拿到推拉流地址,就可以进行直播了。
2:因为我们是要集成代码去进行开发的,现在设计业务表。
3:创建一个直播场次表(live_record),既是每一次开播都是一个新的直播场次。

/*Navicat MySQL Data TransferSource Server         : 192.168.1.105Source Server Type    : MySQLSource Server Version : 50730Source Host           : 111.6.79.10:3317Source Schema         : liveTarget Server Type    : MySQLTarget Server Version : 50730File Encoding         : 65001Date: 16/10/2020 17:41:45
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for live_record
-- ----------------------------
DROP TABLE IF EXISTS `live_record`;
CREATE TABLE `live_record`  (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键的ID\r\n',`live_record_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播的场次ID',`anchor_code` bigint(20) NULL DEFAULT NULL COMMENT '主播code',`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播标题',`label` int(11) NULL DEFAULT NULL COMMENT '直播标签 分类',`live_cover` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播封面',`stream_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '流名称',`push_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '推流地址',`start_time` datetime(0) NULL DEFAULT NULL COMMENT '开播时间',`end_time` datetime(0) NULL DEFAULT NULL COMMENT '关播时间',`stream_end_time` datetime(0) NULL DEFAULT NULL COMMENT '流结束时间(流存活时间)',`showing` int(1) NULL DEFAULT 1 COMMENT '是否正在直播  1正在直播  0 已经直播',`recommend` int(1) NULL DEFAULT 1 COMMENT '是否推荐  0不推荐  1推荐',`watch_num` int(1) NULL DEFAULT 0 COMMENT '观看人数',`like_num` int(1) NULL DEFAULT 0 COMMENT '点赞人数',`location_longitude` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位经度',`location_latitude` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位纬度',`location_province` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位省份',`location_city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位城市',`status` int(11) NULL DEFAULT 1 COMMENT '1正常  预留',`pull_rtmp_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`pull_flv_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`pull_m3u8_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`pull_udp_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`live_module` int(11) NULL DEFAULT NULL COMMENT '0城市1医疗2旅游',`room_number` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播的场次ID  和live_record_id值一样',`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 105 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '直播场次表' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

1:设计完直播场次表(live_record)
2:开播接口---->开播的原理:APP端向java后台发送开播请求,主要是后台代码生成一条开播记录,以及对应的推流拉流地址。App拿到请求回来的(合法的推拉流)推拉流地址,然后调用腾讯云的SDK进行推流,如果调用SDK成功,且推流地址正确,则直播就能被创建成功。拉流也是一样的。调用腾讯云的SDK进行拉流,如果调用SDK成功,且拉流地址正确。直播就能被用户访问且观看。
3:关播接口 ---->关播的原理:APP端(即是安卓,IOS)调用腾讯云的关播断流的SDK,调用成功以后,且调用成功后,再回调java后台,修改后台自己设计的live_record 表的状态值(0:不显示 1:显示)。修改的是我们后台自己的表设计的状态值。
4:送佛送到西,写一套完整的直播的开播流程代码。

直播场次实体

/*** 直播场次表-->根据live_record表进行生成的* @author * @date 2020-10-16 12:11:58*/
@Data
@TableName("live_record")
public class LiveRecord implements Serializable {private static final long serialVersionUID = 1L;/*** 表的主键ID*/@TableId(type = IdType.AUTO)@NotNull(message = "表的主键ID"+"不能为空",groups = UpdateGroup.class)@ApiModelProperty(name = "id",value = "表的主键ID")private Long id;/*** 流名称*/@ApiModelProperty(name = "streamName",value = "流名称")private String streamName;/*** 直播的场次ID*/@ApiModelProperty(name = "liveRecordId",value = "直播的场次ID")private String liveRecordId;/*** 主播code*/@ApiModelProperty(name = "anchorCode",value = "主播code")private Long anchorCode;/*** 直播标题*/@ApiModelProperty(name = "title",value = "直播标题")private String title;/*** 直播标签 分类*/@ApiModelProperty(name = "label",value = "直播标签 分类")private Integer label;/*** 直播封面*/@ApiModelProperty(name = "liveCover",value = "直播封面")private String liveCover;/*** 推流地址*/@ApiModelProperty(name = "pushUrl",value = "推流地址")private String pushUrl;/*** 开播时间*/@ApiModelProperty(name = "startTime",value = "开播时间")private LocalDateTime startTime;/*** 关播时间*/@ApiModelProperty(name = "endTime",value = "关播时间")private LocalDateTime endTime;/*** 流结束时间*/@ApiModelProperty(name = "streamEndTime",value = "流结束时间")private LocalDateTime streamEndTime;/*** 是否正在直播  1正在直播  0 历史直播*/@ApiModelProperty(name = "showing",value = "是否正在直播  1正在直播  0 历史直播")private Integer showing;/*** 是否推荐  0不推荐  1推荐*/@ApiModelProperty(name = "isRecommend",value = "是否推荐  0不推荐  1推荐")private Integer recommend;/*** 观看人数*/@ApiModelProperty(name = "watchNum",value = "观看人数")private Integer watchNum;/*** 点赞人数*/@ApiModelProperty(name = "likeNum",value = "点赞人数")private Integer likeNum;/*** 定位经度*/@ApiModelProperty(name = "locationLongitude",value = "定位经度")private String locationLongitude;/*** 定位纬度*/@ApiModelProperty(name = "locationLatitude",value = "定位纬度")private String locationLatitude;/*** 定位省份*/@ApiModelProperty(name = "locationProvince",value = "定位省份")private String locationProvince;/*** 定位城市*/@ApiModelProperty(name = "locationCity",value = "定位城市")private String locationCity;/*** 1正常  预留*/@ApiModelProperty(name = "status",value = "1正常  预留")private Integer status;/*** 拉流地址*/@ApiModelProperty(name = "pullRtmpUrl",value = "拉流地址")private String pullRtmpUrl;/*** 拉流地址*/@ApiModelProperty(name = "pullFlvUrl",value = "拉流地址")private String pullFlvUrl;/*** 拉流地址*/@ApiModelProperty(name = "pullM3u8Url",value = "拉流地址")private String pullM3u8Url;/*** 拉流地址*/@ApiModelProperty(name = "pullUdpUrl",value = "拉流地址")private String pullUdpUrl;/*** 创建时间*/@ApiModelProperty(name = "createTime",value = "创建时间")private LocalDateTime createTime;/*** 更新时间*/@ApiModelProperty(name = "updateTime",value = "更新时间")private LocalDateTime updateTime;/*** 房间号*/@ApiModelProperty(name = "roomNumber",value = "房间号")private String roomNumber;
}

封装一个推拉流地址实体

package com.*.utils;/*** 推拉流地址*/
public class LiveAddress {private String pushRTMP;private String pullRTMP;private String pullFLV;private String pullM3U8;private String pullUDP;public String getPushRTMP() {return pushRTMP;}public void setPushRTMP(String pushRTMP) {this.pushRTMP = pushRTMP;}public String getPullRTMP() {return pullRTMP;}public void setPullRTMP(String pullRTMP) {this.pullRTMP = pullRTMP;}public String getPullFLV() {return pullFLV;}public void setPullFLV(String pullFLV) {this.pullFLV = pullFLV;}public String getPullM3U8() {return pullM3U8;}public void setPullM3U8(String pullM3U8) {this.pullM3U8 = pullM3U8;}public String getPullUDP() {return pullUDP;}public void setPullUDP(String pullUDP) {this.pullUDP = pullUDP;}}

直播场次生成工具

package com.*.utils;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.ReentrantLock;public class GenerateIdUtil {// 使用单例模式,不允许直接创建实例private GenerateIdUtil() {}// 创建一个空实例对象,类需要用的时候才赋值private static GenerateIdUtil instance = null;// 单例模式--懒汉模式public static synchronized GenerateIdUtil getInstance() {if (instance == null) {instance = new GenerateIdUtil();}return instance;}// 全局自增数private static int count = 1;// 格式化的时间字符串private static final SimpleDateFormat sdf = new SimpleDateFormat("ddHHmmss");// 获取当前时间年月日时分秒毫秒字符串private static String getNowDateStr() {return sdf.format(new Date());}// 记录上一次的时间,用来判断是否需要递增全局数private static String now = null;//定义锁对象private final static ReentrantLock lock=new ReentrantLock();/*** 随机生成11位数字的随机数* @return*/public static String generateIdUtilId(){String Newnumber=null;String dateStr=getNowDateStr();lock.lock();//加锁//判断是时间是否相同if (dateStr.equals(now)) {try {if (count >= 10000){count = 1;}if (count<10) {Newnumber =  getNowDateStr()+"00"+count;}else if (count<100) {Newnumber =   getNowDateStr()+"0"+count;} else {Newnumber =  getNowDateStr()+count;}count++;} catch (Exception e) {}finally{lock.unlock();}}else{count=1;now =getNowDateStr();try {if (count >= 10000){count = 1;}if (count<10) {Newnumber =  getNowDateStr()+"00"+count;}else if (count<100) {Newnumber =  getNowDateStr()+"0"+count;}else  {Newnumber = getNowDateStr()+count;}count++;} catch (Exception e) {}finally{lock.unlock();}}return Newnumber;//返回的值}/*** 生成32位的随机的数字* @return*/public static String generateRandomTO32(int num) {String chars = "0123456789";char[] rands = new char[num];for (int i = 0; i < num; i++) {int rand = (int) (Math.random() * 10);rands[i] = chars.charAt(rand);}return String.valueOf(rands);}
}

直播的开播与关播

Controller层

package com.*.controller;import com.*.entity.LiveRecord;
import com.*.result.ResultObject;
import com.*.service.LiveBroadcastService;
import com.*.vo.LiveBroadCastVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;/*** 开播的模块* @author * @date 2020-10-16 12:11:58*/
@RequestMapping("/liveBroadCast")
public class LiveBroadCastController {@Autowiredprivate LiveBroadcastService liveBroadcastService;@ApiOperation("开播")@PostMapping("/open")public ResultObject open(@RequestBody LiveRecord liveRecord) {ResultObject resultObject = liveBroadcastService.open(liveRecord);return resultObject;}@ApiOperation("关播")@PostMapping("/close")public ResultObject close(@RequestBody LiveBroadCastVO liveBroadCastVO) {ResultObject resultObject = liveBroadcastService.close(liveBroadCastVO);return resultObject;}
}

service层

package com.*.service;
import com.*.entity.LiveRecord;
import com.*.result.ResultObject;
import com.*.vo.LiveBroadCastVO;/*** APP端开播模块* @author * @date 2020-10-16 12:11:58*/
public interface LiveBroadcastService {/*** 开播* @param liveRecord* @return*/ResultObject open(LiveRecord liveRecord);/*** 关播* @param liveBroadCastVO* @return*/ResultObject close(LiveBroadCastVO liveBroadCastVO);}

impl


/*** APP端开播模块* @author * @date 2020-10-16 12:11:58*/
@Service("LiveBroadcastService")
public class LiveBroadcastServiceImpl implements LiveBroadcastService {@Resourceprivate LiveRecordMapper liveRecordMapper;  //这个接口自己去实现@Transactional@Overridepublic ResultObject open(LiveRecord liveRecord) {if (liveRecord.getTitle() == null) {return ResultObject.error("直播标题不能为空");}if (liveRecord.getLocationLatitude() == null || liveRecord.getLocationLongitude() == null) {return ResultObject.error("直播定位没有开启");}if (liveRecord.getLiveCover() == null) {return ResultObject.error("直播的封面未上传");}//开播LocalDateTime localDateTime =  LocalDateTime.now();long nowTime = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
//        long endTime = nowTime + 60*60*2;long endTime = nowTime + 60*3;LiveRecord liveRecord1 = new LiveRecord();String liveRecordId = GenerateIdUtil.generateIdUtilId();liveRecord1.setLiveRecordId(liveRecordId);liveRecord1.setTitle(liveRecord.getTitle());liveRecord1.setLiveCover(liveRecord.getLiveCover());liveRecord1.setAnchorCode(liveRecord.getAnchorCode());
/*        String toString = liveRecord.getAnchorCode().toString();String substring = toString.substring(toString.length()-6, toString.length());*/
//        liveRecord1.setRoomNumber(Integer.parseInt(substring));liveRecord1.setRoomNumber(liveRecordId);liveRecord1.setLocationProvince(liveRecord.getLocationProvince());liveRecord1.setLocationCity(liveRecord.getLocationCity());liveRecord1.setLabel(liveRecord.getLabel());liveRecord1.setLiveModule(liveRecord.getLiveModule());liveRecord1.setStartTime(localDateTime);liveRecord1.setCreateTime(localDateTime);liveRecord1.setShowing(0);  // 默认生成的直播不显示liveRecord1.setStreamEndTime(Instant.ofEpochSecond(endTime).atOffset(ZoneOffset.of("+08:00")).toLocalDateTime());liveRecord1.setLocationLatitude(liveRecord.getLocationLatitude());liveRecord1.setLocationLongitude(liveRecord.getLocationLongitude());LiveAddress addressUrl =AutoAddressUtils.getAddressUrl(liveRecordId, endTime);liveRecord1.setStreamName(liveRecordId);liveRecord1.setPushUrl(addressUrl.getPushRTMP());liveRecord1.setPullFlvUrl(addressUrl.getPullFLV());liveRecord1.setPullM3u8Url(addressUrl.getPullM3U8());liveRecord1.setPullRtmpUrl(addressUrl.getPullRTMP());liveRecord1.setPullUdpUrl(addressUrl.getPullUDP());try {liveRecordMapper.insert(liveRecord1); //自己写一个直播场次数据插入的接口} catch (Exception e) {e.printStackTrace();}return ResultObject.ok(liveRecord1);}@Transactional@Overridepublic ResultObject close(LiveBroadCastVO liveBroadCastVO) {// 修改直播场次的状态if (liveBroadCastVO.getLiveRecordId() == null) {return ResultObject.error("参数异常");}//修改状态值为0liveRecordMapper.updateShowing(liveBroadCastVO); //自己写一个修改直播的状态值的接口return ResultObject.ok("关播成功", null);}
}

如果不考虑直播的其他的一些异常的情况的话,简单的额直播的开播,关播,已经做好了。
把写好的开播,关播接口,提供给APP就行。
如果需要额外帮助:WX:380666989

腾讯云的云直播和即时通讯IM开发(全网最详细之一)相关推荐

  1. 知识付费直播间即时通讯

    知识付费直播间即时通讯使用WebSocket创建.目前,直播间的发信息.送礼物.在线人数.欢迎语和开关播提示都是基于此进行通讯. 浏览器通过JavaScript向服务器发出建立WebSocket连接的 ...

  2. linux+即时通讯服务器,linux平台上的即时通讯应用开发

    由于使用习惯,Linux在中国受欢迎程度远不如windows,相应的软件也比较少,尤其是音视频类的软件,但是,这并不代表就完全没有.下面介绍一款强大的音视频即时通讯平台给大家,它就是--Anychat ...

  3. 融云SDK实现类QQ即时通讯的前端开发

    一.概述 接到一个需求,需要在我们的客户端里实现类似QQ的社交功能,以方便玩家之间的沟通互动.我们的客户端是C++实现的,在开会讨论考虑到成本和时间问题,实现这个功能的任务交个了前端.为了简化说明,我 ...

  4. 即时聊天app开发-即时通讯app开发方案分析

    如今,即时聊天APP层出不穷,它已经成为人们日常生活中密不可分的社交工具.如今,即时聊天APP不仅是聊天工具,也是企业营销的利器.我们经常可以在聊天主页上看到一些广告.如有必要,用户可以直接点击广告了 ...

  5. 即时通讯 IM 开发指南 1:如何进行技术选型

    <移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年 iOS IM SDK 开发的经验,深度分析实际开发中的各种常 ...

  6. 即时通讯应用开发之网络心跳包机制

    一般来说,没有真正动手做过网络通信应用的开发者,很难想象即时通讯应用中的心跳机制的作用.但不可否认,作为即时通讯应用,心跳机制是其网络通信技术底层中非常重要的一环,有没有心跳机制.心跳机制的算法实现好 ...

  7. IM即时通讯系统源码,即时通讯系统开发架构

    IM系统是一种即时通讯系统,可以让用户实时地发送和接收消息,支持文字.图片.语音等多种类型的消息.下面我们来介绍一下IM系统的架构设计和示例代码. IM系统的架构设计 IM系统的架构设计一般包括以下几 ...

  8. 企业即时通讯的开发与发展优势

    企业即时通信:简称EIM(Enterprise Instant Messaging),它是一种面向企业终端使用者的网络沟通工具服务,使用者可以通过安装了即时通信的终端机进行两人或多人之间的实时沟通.交 ...

  9. 腾讯云WebIM和阿里百川即时通讯使用总结

    主要使用流程: 1.注册平台账号 2.创建应用,获取相应的登录凭证 腾讯云:聊天账号所需登录凭证有sdkAppID(所属应用id),identifier(相当于当前登录账户ID),accountTyp ...

最新文章

  1. flutter开发小程序_为什么我认为Flutter是移动应用程序开发的未来
  2. 【django轻量级框架】View与Model交互(模块的交互关系)
  3. 三级网络技术_三级网络技术考前选择题—VLAN
  4. Linux之DNS服务器搭建及常见DNS***和防御
  5. asp伪装成jsp的方法
  6. python3精要(8)-对象,变量,引用
  7. [转载] Java中Scanner用法总结
  8. 哈工大计算机学院成立,哈工大计算机科学与技术学院简介
  9. 漫画:互联网大佬都是这样聊天的
  10. 标签传播(阅读笔记)
  11. ubuntu下使用code::blocks编译运行一个简单的gtk+2.0项目
  12. ssh登录忽略known_hosts列表
  13. Android学习资源网站 1
  14. 蓝桥杯——练习系统登录
  15. 制作PPT如何快速绘制透视立体图
  16. HbuiderX调用微信开发者工具设置
  17. matlab 结构体struct函数使用方法
  18. 求生之路无限火力服务器,《求生之路》终于数3了?还没开测就已经卖疯了……...
  19. C# 打开exe文件
  20. 【终结扩散模型】Consistency Models.OpenAI开源新模型代码,一步成图,1秒18张

热门文章

  1. BOS金蝶云星空二开常用接口插件
  2. Android Studio最全插件
  3. TMF SID性能相关实体介绍
  4. Unity3D使用腾讯广点通广告
  5. Android Drawable (可绘制图像)
  6. 一个简单的文本聚类实现(python)
  7. Java打印字母金字塔
  8. 学物生地对以后学计算机有影响吗,江苏高考改革后的第一届学生选考物生地,有什么问题吗?...
  9. 《互联网+ 电商平台设计与运营》一一1.3 “互联网+”幕后的商家生态
  10. 什么是大数据?大数据能做什么?