一篇文章讲明白iosavplayer视频播放器

简介: 一篇文章讲明白iosavplayer视频播放器

#import

@interface XGGesTuresView : UIView

//左下角播放按钮

@property (nonatomic ,strong)UIButton leftplayerbutton;

//最小时间

@property (nonatomic ,strong)UILabel mintimelable;

//滑动条

@property (nonatomic ,strong)UISlider slider;

//缓冲条

@property (nonatomic ,strong)UIProgressView progressview;

//视频总时长

@property (nonatomic ,strong)UILabel maxtimelable;

//全屏按钮

@property (nonatomic ,strong)UIButton fullbutton;

//右边中间播放按钮

@property (nonatomic ,strong)UIButton rightplayerbutton;

//小菊花

@property (nonatomic ,strong)UIActivityIndicatorView activity;

//视频出错提示 网络提示 用同一个

//@property (nonatomic ,strong)UILabel errorlable;

//返回按钮

@property (nonatomic ,strong)UIButton backbutton;

//标题 可以自己调颜色

@property (nonatomic ,strong)UILabel titlelable;

@end

#import "XGGesTuresView.h"

@implementation XGGesTuresView

- (instancetype)initWithFrame:(CGRect)frame{

if (self =【super initWithFrame:frame】) {

self.backgroundColor = 【UIColor clearColor】;

【self creatUI】;

}

return self;

}

- (void)creatUI{

//左边播放按钮

self.leftplayerbutton = 【UIButton buttonWithType:UIButtonTypeCustom】;

【self.leftplayerbutton setImage:【UIImage imageNamed:@"Stop"】 forState:UIControlStateNormal】;

【self.leftplayerbutton setImage:【UIImage imageNamed:@"Play"】 forState:UIControlStateSelected】;

【self addSubview:self.leftplayerbutton】;

//进度时间lable

self.mintimelable = 【【UILabel alloc】init】;

self.mintimelable.text = @"00:00";

self.mintimelable.textColor = 【UIColor whiteColor】;

self.mintimelable.textAlignment = NSTextAlignmentCenter;

self.mintimelable.font = 【UIFont systemFontOfSize:14】;

【self addSubview:self.mintimelable】;

//缓冲条

self.progressview = 【【UIProgressView alloc】init】;

self.progressview.progressTintColor = 【UIColor magentaColor】;

【self addSubview:self.progressview】;

//滑动条

self.slider = 【【UISlider alloc】init】;

self.slider.minimumTrackTintColor = 【UIColor whiteColor】;

self.slider.maximumTrackTintColor = 【UIColor clearColor】;

【self.slider setThumbImage:【UIImage imageNamed:@"icmpv_thumb_light"】 forState:UIControlStateNormal】;

【self addSubview:self.slider】;

//总时间lable

self.maxtimelable = 【【UILabel alloc】init】;

self.maxtimelable.text = @"00:00";

self.maxtimelable.textColor = 【UIColor whiteColor】;

self.maxtimelable.textAlignment = NSTextAlignmentCenter;

self.maxtimelable.font = 【UIFont systemFontOfSize:14】;

【self addSubview:self.maxtimelable】;

//全屏按钮

self.fullbutton = 【UIButton buttonWithType:UIButtonTypeCustom】;

【self.fullbutton setImage:【UIImage imageNamed:@"Rotation"】 forState:UIControlStateNormal】;

【self addSubview:self.fullbutton】;

//右边播放按钮

self.rightplayerbutton = 【UIButton buttonWithType:UIButtonTypeCustom】;

【self.rightplayerbutton setImage:【UIImage imageNamed:@"player_pause_iphone_window"】 forState:UIControlStateNormal】;

【self.rightplayerbutton setImage:【UIImage imageNamed:@"player_start_iphone_window"】 forState:UIControlStateSelected】;

【self addSubview:self.rightplayerbutton】;

//小菊花

self.activity = 【【UIActivityIndicatorView alloc】initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge】;

self.activity.color = 【UIColor whiteColor】;

【self addSubview:self.activity】;

//视频出错提示

// self.errorlable = 【【UILabel alloc】init】;

// self.errorlable.text = @"亲,视频解析出错了!";

// self.errorlable.textColor = 【UIColor whiteColor】;

// self.errorlable.textAlignment = NSTextAlignmentCenter;

// self.errorlable.hidden = YES;

// 【self addSubview:self.errorlable】;

//返回按钮

self.backbutton = 【UIButton buttonWithType:UIButtonTypeCustom】;

【self.backbutton setImage:【UIImage imageNamed:@"public返回"】 forState:UIControlStateNormal】;

【self addSubview:self.backbutton】;

//标题

self.titlelable = 【【UILabel alloc】init】;

self.titlelable.textColor = 【UIColor whiteColor】;

【self addSubview:self.titlelable】;

}

- (void)layoutSubviews{

【super layoutSubviews】;

self.leftplayerbutton.frame = CGRectMake(10, self.frame.size.height - 40, 30, 30);

self.mintimelable.frame = CGRectMake(CGRectGetMaxX(self.leftplayerbutton.frame), self.frame.size.height - 40, 60, 30);

self.slider.frame = CGRectMake(CGRectGetMaxX(self.mintimelable.frame), self.frame.size.height - 35, self.frame.size.width - 2 CGRectGetMaxX(self.mintimelable.frame), 20);

self.progressview.frame = CGRectMake(self.slider.frame.origin.x + 6, self.slider.frame.origin.y, self.slider.frame.size.width - 12, 2);

self.progressview.center = self.slider.center;

self.maxtimelable.frame = CGRectMake(CGRectGetMaxX(self.slider.frame), self.frame.size.height - 40, 60, 30);

self.fullbutton.frame = CGRectMake(CGRectGetMaxX(self.maxtimelable.frame), self.frame.size.height -40, 30, 30);

self.rightplayerbutton.frame = CGRectMake(self.frame.size.width - 60, self.frame.size.height - 100, 50, 50);

self.activity.frame = CGRectMake(CGRectGetMidX(self.bounds) - 370.5, CGRectGetMidY(self.bounds)-370.5, 37, 37);

//self.errorlable.frame = CGRectMake(self.frame.size.width/ 2 - 100, self.frame.size.height / 2 -10, 200, 20);

self.backbutton.frame = CGRectMake(0, 0, 30, 30);

self.titlelable.frame = CGRectMake(CGRectGetMaxX(self.backbutton.frame), CGRectGetMinY(self.backbutton.frame), self.frame.size.width - CGRectGetMaxX(self.backbutton.frame), 30);

}

- (void)dealloc{

}

上面这些是提示视图 和 手势视图 下面是主要 用avplayer 来播放 代码可以复制到你的工程里 把类改一下就行

#import

@protocol XGAVPlayerViewdelegate

//全屏

- (void)XGAVPlayerViewfullScreen:(BOOL)fullscreen;

//返回

- (void)XGAVPlayerViewback;

@end

@interface XGAVPlayerView : UIView

//代理

@property (nonatomic ,weak)iddelegate;

//本地和网络亦可

- (void)setUrl:(NSURL )url andIsStartplay:(BOOL)isstartplay;

//

- (void)closeplay;

@end

#import "XGAVPlayerView.h"

#import "Reachability.h"

#import "XGGesTuresView.h"

#import

#import

#import

@interface XGAVPlayerView ()

//播放工具

@property (nonatomic ,strong)AVPlayer player;

//播放图层

@property (nonatomic ,strong)AVPlayerLayer playerlayer;

//播放资源对象

@property (nonatomic ,strong)AVPlayerItem playeritem;

//手势视图

@property (nonatomic ,strong)XGGesTuresView gesturesview;

//错误lable

@property (nonatomic ,strong)UILabel errorlable;

//重连

@property (nonatomic ,strong)UIButton reconnectbutton;

@property (nonatomic ,strong)CTCallCenter telephone;

//播放地址

@property (nonatomic ,strong)NSURL playerurl;

//player时间观察者

@property (nonatomic ,strong)id playTimeObserver;

//是否正在播放

@property (nonatomic ,assign)BOOL isplaying;

//是否开始播放 可从外界控制

@property (nonatomic ,assign)BOOL isstartplay;

//网络

@property (nonatomic ,assign)NetworkStatus netstatus;

@end

@implementation XGAVPlayerView

//初始化

- (instancetype)initWithFrame:(CGRect)frame{

if (self = 【super initWithFrame:frame】) {

self.backgroundColor = 【UIColor blackColor】;

【self creatAvPlayer】;

【self creatUI】;

【self addtap】;

}

return self;

}

//播放管理

- (void)creatAvPlayer{

self.player = 【【AVPlayer alloc】init】;

self.playerlayer = 【AVPlayerLayer playerLayerWithPlayer:self.player】;

self.playerlayer.videoGravity = AVLayerVideoGravityResizeAspect;

【self.layer insertSublayer:self.playerlayer atIndex:0】;//放到最底层

}

//视图

- (void)creatUI{

//错误

self.errorlable = 【【UILabel alloc】init】;

self.errorlable.textColor = 【UIColor whiteColor】;

self.errorlable.textAlignment = NSTextAlignmentCenter;

self.errorlable.hidden = YES;

【self addSubview:self.errorlable】;

//重连

self.reconnectbutton = 【UIButton buttonWithType:UIButtonTypeCustom】;

【self.reconnectbutton setTitle:@"重 连" forState:UIControlStateNormal】;

self.reconnectbutton.backgroundColor = 【UIColor greenColor】;

self.reconnectbutton.hidden = YES;

【self.reconnectbutton addTarget:self action:@selector(notreachableclick) forControlEvents:UIControlEventTouchUpInside】;

【self addSubview:self.reconnectbutton】;

//手势视图

self.gesturesview = 【【XGGesTuresView alloc】init】;

【self addSubview:self.gesturesview】;

self.gesturesview.slider.value = 0.0;//滑动条初始值

self.gesturesview.progressview.progress = 0.0;//缓冲条初始值

【self.gesturesview.leftplayerbutton addTarget:self action:@selector(playclick) forControlEvents:UIControlEventTouchUpInside】;

【self.gesturesview.fullbutton addTarget:self action:@selector(fullclick:) forControlEvents:UIControlEventTouchUpInside】;

【self.gesturesview.rightplayerbutton addTarget:self action:@selector(playclick) forControlEvents:UIControlEventTouchUpInside】;

【self.gesturesview.backbutton addTarget:self action:@selector(backclick) forControlEvents:UIControlEventTouchUpInside】;

【self.gesturesview.slider addTarget:self action:@selector(palyslidertouchdown:) forControlEvents:UIControlEventTouchDown】;//按下

【self.gesturesview.slider addTarget:self action:@selector(palysliderdrop:) forControlEvents:UIControlEventValueChanged】;//拖动

【self.gesturesview.slider addTarget:self action:@selector(palysliderdropfinish:) forControlEvents:UIControlEventTouchUpInside】;//点击

}

//播放 暂停

- (void)playclick{

self.isplaying ? 【self stopplay】 :【self startplay】;

}

//全屏

- (void)fullclick:(UIButton )sender{

sender.selected = !sender.selected;

if (self.delegate 【self.delegate respondsToSelector:@selector(XGAVPlayerViewfullScreen:)】){

【self.delegate XGAVPlayerViewfullScreen:sender.selected】;

}

}

//返回 如果反回到原始图(竖屏) 记得改变全屏按钮状态 如果返回到上一个控制器 则不需要改变全屏按钮状态 这里自定义

- (void)backclick{

【self stopplay】;

if (self.delegate 【self.delegate respondsToSelector:@selector(XGAVPlayerViewback)】){

【self.delegate XGAVPlayerViewback】;

}

}

//按下

- (void)palyslidertouchdown:(UISlider )sender{

【self.player pause】;

if (self.isplaying == YES) {

self.gesturesview.leftplayerbutton.selected = YES;

self.gesturesview.rightplayerbutton.selected = YES;

}

【【self class】 cancelPreviousPerformRequestsWithTarget:self selector:@selector(showgesturesview) object:nil】;

}

//拖动

- (void)palysliderdrop:(UISlider )sender{

CMTime changetime = CMTimeMakeWithSeconds(sender.value, 1.0);

self.gesturesview.mintimelable.text = 【self convertTime:CMTimeGetSeconds(changetime)】;

}

//拖动结束

- (void)palysliderdropfinish:(UISlider )sender{

CMTime changetime = CMTimeMakeWithSeconds(sender.value, 1.0);

【self.playeritem seekToTime:changetime completionHandler:^(BOOL finished) {

self.isplaying ? 【self startplay】 : nil;

}】 ;

}

//手势

- (void)addtap{

UITapGestureRecognizer tap = 【【UITapGestureRecognizer alloc】initWithTarget:self action:@selector(showgesturesview)】;

tap.delegate = self;

【self addGestureRecognizer:tap】;

}

//手势方法

- (void)showgesturesview{

【【self class】 cancelPreviousPerformRequestsWithTarget:self selector:@selector(showgesturesview) object:nil】;

【UIView animateWithDuration:0.25 animations:^{

self.gesturesview.hidden = !self.gesturesview.hidden;

【【UIApplication sharedApplication】setStatusBarHidden:self.gesturesview.hidden withAnimation:UIStatusBarAnimationFade】;

} completion:nil】;

}

//手势代理 用来解决uislider和tap 的手势冲突

- (BOOL)gestureRecognizer:(UIGestureRecognizer )gestureRecognizer shouldReceiveTouch:(nonnull UITouch )touch{

if (【touch.view isKindOfClass:【UISlider class】】) {

return NO;

}

return YES;

}

//本地和网络亦可

- (void)setUrl:(NSURL )url andIsStartplay:(BOOL)isstartplay{//进来优先检查网络

self.isstartplay = isstartplay;

self.playerurl = url;

NetworkStatus firststatus = 【self CheckNowNetWorkStatus】;

switch (firststatus) {

case NotReachable:{//进来时没网络

【self notreachable】;

}break;

case ReachableViaWiFi:{//进来wifi

【self reachableviawifi:url】;

}break;

case ReachableViaWWAN:{//进来时没网络

UIAlertView firstalert = 【【UIAlertView alloc】initWithTitle:@"温馨提示" message:@"当前处于2g/3g/4g模式下,继续播放会产生流量!" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil】;

firstalert.tag = 1;

【firstalert show】;

}break;

default:

break;

}

}

//无网络提示

- (void)notreachable{

【self stopplay】;

self.errorlable.hidden = NO;

self.errorlable.text = @"亲,没有网络!";

self.reconnectbutton.hidden = NO;

self.gesturesview.userInteractionEnabled = NO;

}

//刚进来时无网络状态 没有创建self.playeritem 和监听 所以不影响后面的

- (void)notreachableclick{

NetworkStatus reconnect = 【self CheckNowNetWorkStatus】;

switch (reconnect) {

case NotReachable:{//重连 无网络点击 不做任何反应

NSLog(@"无网络");

}break;

case ReachableViaWiFi:{//wifi

NSLog(@"wifi");

}

case ReachableViaWWAN:{//在流量状态重连 表示用户默认接受了流量状态下播放 wifi就不用说了

【self reachableviawifi:self.playerurl】;

}break;

default:

break;

}

}

//wifi

- (void)reachableviawifi:(NSURL )url{

//代码效果参考:http://www.zidongmutanji.com/zsjx/473665.html

self.errorlable.hidden = YES;

self.reconnectbutton.hidden = YES;

self.gesturesview.userInteractionEnabled = YES;

if (【url.absoluteString hasPrefix:@"http"】 ||【url.absoluteString hasPrefix:@"https"】){//网络视频 添加网络监听

self.playeritem = 【AVPlayerItem playerItemWithURL:【NSURL URLWithString:【url.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding】】】;

【self addnetworkNotification】;

}else{//本地

self.playeritem = 【AVPlayerItem playerItemWithURL:url】;

}

【self.player replaceCurrentItemWithPlayerItem:self.playeritem】;

【self addNotification】;

}

//网络监控

- (void)addnetworkNotification{

【【NSNotificationCenter defaultCenter】addObserver:self selector:@selector(netchange:) name:kReachabilityChangedNotification object:nil】;

}

//网络状态

- (void)netchange://代码效果参考:http://www.zidongmutanji.com/zsjx/246679.html

(NSNotification )noti{

Reachability reach = 【noti object】;

if (【reach isKindOfClass:【Reachability class】】) {

NetworkStatus status = 【reach currentReachabilityStatus】;

【self updatenetworkstatus:status】;

}

}

//根据网络 改变播放状态

- (void)updatenetworkstatus:(NetworkStatus)status{

switch (status) {

case NotReachable:{//无网络

【self notreachable】;

}break;

case ReachableViaWiFi:{

self.errorlable.hidden = YES;

self.reconnectbutton.hidden = YES;

self.gesturesview.userInteractionEnabled = YES;

}break;

case ReachableViaWWAN:{//2g3g4g

【self stopplay】;

UIAlertView wwanalert = 【【UIAlertView alloc】initWithTitle:@"温馨提示" message:@"当前处于2g/3g/4g模式下,继续播放会产生流量!" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil】;

wwanalert.tag = 2;

【wwanalert show】;

}break;

default:

break;

}

}

//alert代理

- (void)alertView:(UIAlertView )alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{

switch (alertView.tag) {

case 1:{

if (buttonIndex != alertView.cancelButtonIndex) {

【self reachableviawifi:self.playerurl】;

}

}break;

case 2:{

if (buttonIndex != alertView.cancelButtonIndex) {

【self startplay】;

}

}break;

default:

break;

}

}

//通知

- (void)addNotification {

//kvo监听

【self.playeritem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil】;

// 监听loadedTimeRanges属性

【self.playeritem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil】;

// 播放完成通知

【【NSNotificationCenter defaultCenter】 addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil】;

// 前台通知

【【NSNotificationCenter defaultCenter】 addObserver:self selector:@selector(enterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil】;

// 后台通知

【【NSNotificationCenter defaultCenter】 addObserver:self selector:@selector(enterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil】;

【self monitoringPlayback:self.playeritem】;

}

//键值观察

- (void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void )context {

if (【keyPath isEqualToString:@"status"】){//状态

AVPlayerStatus status = 【【change objectForKey:@"new"】 intValue】;

if (status == AVPlayerStatusReadyToPlay) {

AVPlayerItem item = (AVPlayerItem )object;

self.gesturesview.slider.maximumValue = CMTimeGetSeconds(item.duration);// 获取视频长度 设置视频时间

self.gesturesview.maxtimelable.text = 【self convertTime:CMTimeGetSeconds(item.duration)】;// 设置视频时间

self.isstartplay ? 【self startplay】:【self stopplay】;// 进来开始播放 进来暂停暂停

}else if (status == AVPlayerStatusFailed){//当地址不对 无网络时 会走此方法

NSLog(@"AVPlayerStatusFailed");

【self stopplay】;

self.errorlable.hidden = NO;

self.errorlable.text = @"亲,视频解析出错了!";

self.gesturesview.userInteractionEnabled = NO;

}else {

NSLog(@"AVPlayerStatusUnknown");

}

} else if (【keyPath isEqualToString:@"loadedTimeRanges"】){

NSTimeInterval timeInterval = 【self availableDurationRanges】; // 缓冲时间

CGFloat totalDuration = CMTimeGetSeconds(self.playeritem.duration); // 总时间

【self.gesturesview.progressview setProgress:timeInterval / totalDuration animated:YES】;//更新缓冲条

}

}

// 相对格林时间

- (NSString )convertTime:(CGFloat)second {

NSDate date = 【NSDate dateWithTimeIntervalSince1970:second】;

NSDateFormatter formatter = 【【NSDateFormatter alloc】 init】;

if (second / 3600 >= 1) {

【formatter setDateFormat:@"HH:mm:ss"】;

} else {

【formatter setDateFormat:@"mm:ss"】;

}

NSString showTimeNew = 【formatter stringFromDate:date】;

return showTimeNew;

}

// 缓冲时间 计算

- (NSTimeInterval)availableDurationRanges {

NSArray loadedTimeRanges = 【self.playeritem loadedTimeRanges】; // 获取item的缓冲数组

CMTimeRange timeRange = 【loadedTimeRanges.firstObject CMTimeRangeValue】; // 获取缓冲区域

float startSeconds = CMTimeGetSeconds(timeRange.start);// CMTimeRange 结构体 start duration 表示起始位置 和 持续时间

float durationSeconds = CMTimeGetSeconds(timeRange.duration);

NSTimeInterval result = startSeconds + durationSeconds; // 计算总缓冲时间 = start + duration

return result;

}

//播放完成通知

- (void)playbackFinished:(NSNotification )notification {

self.playeritem = 【notification object】;

【self.playeritem seekToTime:kCMTimeZero】; // 跳转到初始

【self stopplay】;//暂停

self.gesturesview.hidden = NO;

//【self startplay】;//开始 无限循环

}

//进入前台

- (void)enterForeground:(NSNotification )notification {

NSSet currentsset = self.telephone.currentCalls;

if (currentsset == nil) {

if(!self.isplaying){//切刀后台最后一刻的状态

【self startplay】;

}

}

}

//进入后台

- (void)enterBackground:(NSNotification )notification {

【self stopplay】;

}

// 观察播放进度 每秒执行1次, CMTime 为1秒

- (void)monitoringPlayback:(AVPlayerItem )item {

__weak typeof(self)WeakSelf = self;

self.playTimeObserver = 【self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {

//当前播放时间 秒

float currentPlayTime = (double)item.currentTime.value/ item.currentTime.timescale;

WeakSelf.gesturesview.slider.value = currentPlayTime;

WeakSelf.gesturesview.mintimelable.text = 【WeakSelf convertTime:currentPlayTime】;

}】;

}

//开始播放

- (void)startplay{

self.isplaying = YES;

【self.player play】;

self.gesturesview.leftplayerbutton.selected = NO;

self.gesturesview.rightplayerbutton.selected = NO;

【self performSelector:@selector(showgesturesview) withObject:nil afterDelay:5.0】;

}

//暂停播放

- (void)stopplay{

self.isplaying = NO;

【self.player pause】;

self.gesturesview.leftplayerbutton.selected = YES;

self.gesturesview.rightplayerbutton.selected = YES;

【【self class】 cancelPreviousPerformRequestsWithTarget:self selector:@selector(showgesturesview) object:nil】;

}

//约束

- (void)layoutSubviews{

【super layoutSubviews】;

self.playerlayer.frame = self.bounds;

self.gesturesview.frame = self.bounds;

self.errorlable.frame = CGRectMake(self.frame.size.width/ 2 - 150, self.frame.size.height / 2 -20, 300, 20);

self.reconnectbutton.frame = CGRectMake(self.frame.size.width/ 2 - 30, CGRectGetMaxY(self.errorlable.frame) + 10, 60, 30);

}

//第一次进入页面判断网络状态使用

- (NetworkStatus)CheckNowNetWorkStatus{

NSArray subviews = 【【【【UIApplication sharedApplication】 valueForKey:@"statusBar"】 valueForKey:@"foregroundView"】 subviews】;

NSNumber dataNetworkItemView = nil;

for (id subview in subviews) {

if(【subview isKindOfClass:【NSClassFromString(@"UIStatusBarDataNetworkItemView") class】】) {

dataNetworkItemView = subview;

break;

}

}

switch (【【dataNetworkItemView valueForKey:@"dataNetworkType"】integerValue】) {

case 0:NSLog(@"No wifi or cellular");

return NotReachable;

break;

case 1:NSLog(@"2G");

case 2:NSLog(@"3G");

case 3:NSLog(@"4G");

nbsp

相关文章
|
存储 NoSQL 算法
从一个crash问题展开,探索gcc编译优化细节
问题分析的过程也正是技术成长之路,本文以一个gcc编译优化引发的crash为切入点,逐步展开对编译器优化细节的探索之路,在分析过程中打开了新世界的大门……
|
网络协议 Android开发 开发工具
国内常用的Android镜像下载地址(附教育网主要镜像站)
终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~ Android developer 最新国内镜像:http://wear.
22589 0
|
12月前
|
机器学习/深度学习 人工智能 自然语言处理
探索人工智能在教育领域的应用与挑战
随着科技的不断进步,人工智能(AI)技术已经深入到社会的各个领域,其中教育领域尤为突出。本文旨在探讨人工智能在教育领域的应用现状、面临的挑战以及未来的发展趋势。通过分析AI技术如何改变传统教学模式,提高教育质量和效率,同时指出其在实际应用中可能遇到的问题和挑战,为未来教育的发展提供参考。
784 2
|
12月前
|
安全 网络协议 应用服务中间件
内网ip申请SSL证书实现https访问
内网IP地址虽不能直接申请公网SSL证书,但可通过IP SSL证书保障数据安全。流程包括:确定固定内网IP,选择支持内网IP的CA,注册申请证书,生成CSR,验证IP所有权,下载部署证书至Web服务器,测试HTTPS访问,确保配置正确及证书有效。此方法适用于内网环境,提升数据传输安全性。
内网ip申请SSL证书实现https访问
|
监控 安全 网络协议
Linux监控和调优:提高系统性能的实用技巧与建议
Linux监控和调优:提高系统性能的实用技巧与建议
1287 0
|
11月前
|
安全 Docker 容器
docker的默认网络模式有哪些
Docker 默认网络模式包括:1) bridge:默认模式,各容器分配独立IP,可通过名称或IP通信;2) host:容器与宿主机共享网络命名空间,性能最优但有安全风险;3) none:容器隔离无网络配置,适用于仅需本地通信的场景。
472 6
|
安全
神秘代码
这是针对IDEA 2023.2.4的破解码,允许用户免费激活软件。该破解码包含详细的授权信息,能绕过付费使用限制,实现全面功能解锁。注意,使用此类破解码可能违反相关软件使用协议,并存在安全风险。建议通过官方渠道获取正版软件。
10368 0
|
12月前
|
运维 监控 Serverless
揭秘云计算中的Serverless架构:优势、挑战与实践
揭秘云计算中的Serverless架构:优势、挑战与实践
396 0
|
存储 缓存 网络协议
Linux网络协议栈(二)——套接字缓存(socket buffer)
Linux网络核心数据结构是套接字缓存(socket buffer),简称skb。它代表一个要发送或处理的报文,并贯穿于整个协议栈。1、    套接字缓存skb由两部分组成:(1)    报文数据:它保存了实际在网络中传输的数据;(2)    管理数据:供内核处理报文的额外数据,这些数据构成了协议之间交换的控制信息。
1287 0