热身运动🏂 在开始之前,先来个热身运动。虽然标题党写着快速打造一个ssh客户端,但是和跑步一样,在运动前还是需要先热身一下,不然到时候身体(大脑)会吃不消。所以,在开始前,我们先来科普一下ssh的一些东西。 先来说说ssh,这里的ssh是指由IETF的网络小组(Network Working Group)所制定的为建立在应用层和传输层基础上的安全协议。(对于了解这个协议的请忽略本段文字😱)点这里了解更多ssh介绍 写过java web应用的同学应该还知道另一个ssh(struts+spring+hibernate),当然今天的主角并不是它。😅 其实接触过后端开发的同学对于ssh应该都不陌生,可能每天你都在使用它,没错,当你要远程登录服务器的时候,大多数情况下都离不开它,俨然已经成为Linux系统的标准配置。所以,如果你使用的是Linux操作系统,那么默认情况下就已经自带ssh的客户端了,于是乎你直接可以在Linux的shell中执行: ssh user@host 就可以安全的登录到了远程主机host。对于ssh的更多命令或者玩法今天就不多介绍了,因为这不是今天的主要目标,今天的主要任务是实现一个和Linux操作系统中默认自带的ssh命令行客户端一样的使用go语言开发的ssh命令行客户端,当然由于时间篇幅有限,这次并不会实现原生ssh命令行客户端的全部功能,主要是能够实现远程登录到远程host,并能进行命令行操作。对于其他高级命令,如端口转发等将在后续完成。 工欲善其事必先利其器🔪 既然说了要快速打造,那么必然需要借助一些现有的工具包了,这边为了完成这个客户端,笔者对原生的go语言的ssh包进行了一下封装做了一个小工具包gosshtool,可以从
首先介绍下今天的两个主角:nfs和docker nfs 是什么 NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。 摘自百度百科 docker 是什么 这个就不多说了,近两年一个非常流行的东西哦。 主角介绍完毕,那么要说说为什么要使用docker来搭建nfs,其实本文标题已经说明,主要目的还是为了实现容器间文件的共享。 用过docker的都应该知道docker可以支持容器目录挂载到宿主机。而通过nfs,则可以将容器之间的目录实现共享挂载。如果你有多个容器间需要共享文件的需求,这个将是一个可以尝试的方案,具体使用场景看大家发挥想象了,今天这里主要实践一下如何实现这个功能。 涉及到的知识 nfs安装 docker容器间通信 docker privileged dockerfile docker镜像 编写dockerfile FROM ubuntu ENV DEBIAN_FRONTEND noninteractive RUN apt-get update -qq && apt-get install -y nfs-kernel-server runit inotify-tools -qq RUN mkdir -p /exports VOLUME /exports EXPOSE 111/udp 2049/tcp 制作do
问题描述 通过docker pull命令来pull私有仓库image出现报错: FATA[0010] Error: v1 ping attempt failed with error: Get https://111.xx.xx.xx/v1/_ping: dial tcp 111.xx.xx.xx:443: i/o timeout. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add --insecure-registry 111.xx.xx.xx to the daemon’s arguments. In the case of HTTPS, if you have access to the registry’s CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/111.xx.xx.xx/ca.crt 根据错误提示,是CA的问题,我们需要在docker的启动参数加上-insecure-registry 111.xx.xx.xx,所以我们需要在vi /etc/default/docker,加上 DOCKER_OPTS="$DOCKER_OPTS --insecure-registry=111.xx.xx.xx" 然后重启Docker sudo service docker restart 但是,如果你是在OS X系统下使用boot2docker的,那么通过boot2docker ssh 进入到虚拟机,操作上述方法是不行的,当然有其他办法,那就是ssh到boot2docker虚拟机,然后修改vi /var/lib/boot2do
零、关于快速学习ios开发系列文章 为什么会要写这个系列? 这是个好问题,其实我也不知道这个系列是否会和其他系列一样写着写着就搁置好多了,然后不知道什么时候才更新。但是无所谓,因为本来就是主要用来记录个人学习过程的,如果在这过程中能够帮助到别人也算是一件不错的事情。所以不要太期望文章一定会及时或者持续更新下去,就比如博客中其他文章一样,因为很多也只是记录个人学习历程,如果某个技术在实际工作或者学习中不需要继续深究下去了,可能就不会及时持续更新了,因为要忙的事情实在太多,当然,如果有时间的话,我还是非常希望能把未完结的所有系列文章都给来个大结局。这不,最近入手了Mac,当然得学习学习ios了。如果你也是新手,可以跟着一起玩玩。 一、需要准备的 一台Mac Mac里装个Xcode,这里版本是6.1.1 一只会编程的猴子 上述三个条件,前面两个应该都比较好搞定,第三个需要一个会编程的猴子,这个条件就比较特殊了,因为每只猴子的基础都不一样啊,什么?你不知道猴子是什么?那估计你不需要往下看了。当然猴子的基础越好,就越能掌握本系列的精髓-快速。所以,在学习过程中绝对不是那种《xxx入门》什么类型的,会花很多时间先来学学oc语言语法,然后一步一步截图展示如何创建一个hello world。所以做好准备,可能在学习过程中,你会需要另外去查阅资料。 二、从xxx语言到Objective-C 在ios开发中现在可以使用Objective-C或者是Swift开发语言。这里学习为什么不选Swift呢?虽然她比较新,而且相信未来发展也是非常不错的,但是目前第三方支持或者一些坑可能都没有前人踩过,所以还是选择稳定且但比较旧的Objective-C。当然,对于像笔者这样喜欢尝试各种语言的,到时候切换Swift也说不会有任何困难的。所以,这个标题也就变成了xxx语言到Objective-C了,因为笔者并不是从某一种语言转来的,而是一堆。所以我会在不同语言角度来看Objective-C的语法来对比,当然还是会选择一些比较常用的语言。 所以如果你还没有学过其他编程语言,可能就比较惨了,因为快速入门是建立在之前基础
一、主要步骤 创建一个免费的Admob账户: (http://www.google.com/ads/admob/39)[http://www.google.com/ads/admob/39] 创建一个新的app ID,并设置类型为插页广告的AdMob广告单元 导入Google Play services,在eclipse中选择Windows -> Android SDK Manager -> Extras -> “Google Play services” -> Install packages 修改AndroidManifest.xml文件新增如下代码: AndroidManifest.xml 修改AppActivity.java类如下: AppActivity.java public
一、响应android的back按键 我们都知道,cocos2d-x可以方便的构建不同平台的应用,当我们构建基于android的应用时,有时候我们可能需要用到android的返回按键。当然这个返回按键在iPhone手机上是找不到的(目前还是如此)。既然android有这个按键,cocos2d-x当然不会对它置之不理,在cocos2d-x可以方便的通过程序来响应返回按键动作。 二、简单的例子 这个例子是基于cocos2d-x 3.0的,以前的版本不一样哦,所以一定要看清楚你现在用的是什么版本。在cocos2d-x 3.0中,Layer类中有一个 virtual void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event); 这样的虚方法,我们要想响应用户的按键动作,可以在相应的Layer中重写这个函数。为了方便在不同Layer中使用,我这里写了一个BaseLayer,这样如果想要在某个定义的Layer中响应onKeyReleased事件,只需要继承BaseLayer就可以了。 BaseLayer.h #ifndef __BASE_LAYER_H__ #define __BASE_LAYER_H__ #include "cocos2d.h" using namespace cocos2d; class BaseLayer:public Layer{ public: virtual void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event); bool virtual init(); }; #endif BaseLayer.cpp #include "BaseLayer.h" void BaseLayer::onKeyReleased(EventKeyboard
一、创建菜单场景 我们在一个游戏中,通常打开游戏后都会有一个菜单场景,在菜单场景中你可以点击开始按钮,也可以点击其它例如设置等按钮。这是一个非常通用的场景,今天就来尝试创建一个menu的场景。 二、简单的例子 - hello Menu Scene 首先创建一个场景类: MenuScene.h #ifndef __MENU_SCENE_H__ #define __MENU_SCENE_H__ #include "cocos2d.h" using namespace cocos2d; class MenuScene:public Scene{ public: MenuScene(); ~MenuScene(); virtual bool init(); CREATE_FUNC(MenuScene); }; #endif MenuScene.cpp #include "MenuScene.h" #include "MenuLayer.h" #include "BackgroundLayer.h" MenuScene::MenuScene(){}; MenuScene::~MenuScene(){}; bool MenuScene::init(){ if(!Scene::init()){ return false; } auto bgLayer = BackgroundLayer::create(); if(bgLayer){ this->addChild(bgLayer); } auto menuLayer = MenuLayer::create(); if(menuLayer){ this->addChild(menuLayer); } return true; } 可以看到在实现类中,我们在Scene中添加了两个层,一个是背景
愉快的周末 这个应该是本博客的第一篇非技术类文章。之前一直不想发非技术类的文章,觉得要发点有用的东西给读者看才好,不过,今天就破例一次了。因为今天是一个愉快的周末。原因是今天一口气修复了基于Go语言的静态博客引擎(gosk)的好几个bug,真是大快人心。其实这些bug遗留很久了,一直没这个动力去修复,其中一个就是如果编辑的文章里面有代码,对于代码高亮处理有些bug,对于类xml的代码(包含小尖括号的code)需要真实以代码显示的,到前台却一起和其它文章内容一样被转码了,之前方法是放在前台脚本中js来处理,虽然勉强实现了,但是有各种bug,而且速度超慢。之前一直拖着,觉得这个东西可能要花些时间才能搞定,就不想浪费时间,今天实在是忍不下去了,结果没想象中的那么花费时间。看来有时候只要下决心,一些你想像很麻烦的事情其实也没那么麻烦,一个拖了将近半年的问题,一会会解决。另外还更新了cocos2d-x的一篇小文章,顺带完成了最近在做的一个游戏的一个场景。 ##文档信息 版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 原文网址:http://www.cocosk.com/articles/2014⁄6/15/talk-today.html 作者:卧雪Sirk
一、创建物理世界 在cocos2d-x 3.0版本中,封装了方便模拟物理世界操作的一系列physicals类,在这之前一般是将box2d或者chipmunk集成到cocos2d-x中来。而现在,就方便多了,到底多简单?看看就知道。接下来就来实现一个简单的物理世界吧。 二、简单的例子 - hello Physicals world 首先创建一个场景: PhyScene.h #ifndef __PHY_SCENE_H__ #define __PHY_SCENE_H__ #include "cocos2d.h" using namespace cocos2d; class PhySceneDemo:public Layer{ public: virtual bool init(); static Scene* scene(); CREATE_FUNC(PhySceneDemo); void setPhyWorld(PhysicsWorld *phyworld){this->m_world=phyworld;} void PhySceneDemo::onTouchesEnded(const std::vector& touches, Event *event); private: PhysicsWorld *m_world; }; #endif PhyScene.cpp #include "PhyScene.h" Scene* PhySceneDemo::scene(){ auto scene = Scene::createWithPhysics(); auto layer = PhySceneDemo::create(); layer->setPhyWorld(scene->getPhysicsWorld()); scene->addChild(layer); return scene; } bool
前言 这几天有个小伙伴要实现http协议的服务器推的业务,于是就简单实现了下,且利用客户端模拟持续发送请求,模拟双向通信,当然只是一种简单的模型,如要应用于实际请慎重! 客户端代码: package com.test.client; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; public class HttpLongConnectionClient { public static void main(String[] args) { try { URL url = new URL("http://localhost:8080/TestWeb/test.do"); ReqRunnable rr = new ReqRunnable(url); Thread reqThread = new Thread(rr); reqThread.start(); InputStream in=url.openStream(); int n = -1; byte[] b = new byte[1024]; while((n=in.read(b))!=-1) { String s=new String(b,0,n); System.out.println(s); } } catch (Exception e) { e.printStackTrace(); } } static class ReqRunnable implements Runnable{ URL url; ReqRu
一、关于TexturePacker TexturePacker是一个游戏图片打包工具,通过它,我们可以方便的将多个帧图片合成一张大图,来提高性能,对于这点在手机平台的游戏显得尤为重要。更多的资料可以参考官网:http://www.codeandweb.com/texturepacker 二、简单的例子 首先我们找来三张小图,连起来就代表一个游戏人物的的行走动画: 然后打开,TexturePacker工具将它们依次拖入工具右侧的资源窗口,如下图: 然后在左侧的Data Format选择cocos2d,Data File选择一个路径保存文件,最后点击publish。这样在你之前选择的保存文件的路径下,可以找到两个文件,一个是合成的大图文件,一个是plist文件。在这里是hero.png和hero.plist 三、创建精灵动画 首先创建一个cocos2d-x的cpp工程,然后将上一步骤得到的两个文件都放入Resources目录下。然后创建一个场景: HeroScene.h #pragma once #include "cocos2d.h" using namespace cocos2d; class HeroScene :public Layer{ public: static Scene* scene(); virtual bool init();
前言 在上一篇中,我们介绍了spring自动装配(autowire)的特性。而从系列一开始,我们似乎就一直在xml配置文件中捣鼓,包括上篇的自动装配。不过,自从spring2.5开始,spring还支持了基于注解(annotation)的配置方式。那么这篇我们就来介绍下这个特性,看看它能给我们带来多大的惊喜。 基于annotation的配置 在默认情况下,spring的annotation是没有开启的,为了支持这一特性,我们需要修改下配置文件如下: 只要加入
前言 今天,主要介绍下spring的自动装配特性。看了之前的文章,我们已经看到依赖注入的强大之处,但是你会发现当一个bean依赖另一个bean的时候,你需要在xml配置文件中定义如下的元素引用: 上述代码中,id为tv的bean注入了id为screen的bean,而且是通过setter注入的,所以必须在id为tv的bean中添加 如果还有其他的属性需要注入,也是需要依次添加上述的标签定义的。试想一下,如果你有很多bean,并且很多需要注入的依赖属性,那么你的xml配置文件将会变得非常庞大。为了解决这个问题,spring提供了一个自动装配的特性,它可以自动搜集bean,并且将依赖自动装配装配到需要的bean中去。 spring自动装配的几种类型 byName 通过属性名称进行自动装配。spring容器通过查找在xml配置文件中autowire属性被设置为byName的bean。然后它会去试着匹配配置文件中其它bean,如果那个bean名称和需要注入的属性名称一样,就进行装配。 byType 通过属性数据类型进行自动装配。与上述byName类似,不过进行匹配的时候是根据数据类型进行匹配。 constructor 和byType类似,不过类型是根据构造方法的类型进行匹配。 autodetect 首先尝试通过构造方法进行装配,如果不成功,则通过byType进行自动装配。 一个根据byNa
前言 这几天放假,昨天把网站主题稍微改了下,所以没继续更新,今天趁热打铁,继续spring新手攻略系列。有时候真的是需要长期坚持,虽然文章不长,也没什么复杂的东西,但是坚持完成却似乎很难。因为每次都会把某系列文章更新到一半就没了,所以这次决定下狠心一定要写完了,所以,今天我们继续,今天主要讲下spring注入中对于集合类(Collection)的注入。如果你看了本系列的前几篇文章,对于今天的内容,其实是非常熟悉的,其实说到底还是注入的概念,只是注入的东西不一样了,而且你会发现使用spring其实只要遵循它规定的那种模式,其实使用起来非常方便,当然这里只是指对于初级玩家使用。为什么这么说,因为spring用起来非常简单,但是本身框架的设计确有很多可以学习鉴戒之处,对于这部分,希望今后能有机会写写。好吧,那么今天就正式进入主题: 几种注入的集合配置元素 《list》使用该配置元素,可以注入一个list,这个list可以包含重复元素值 《set》使用该配置元素,可以注入一个set集合,不能包含重复元素 《map》使用该配置元素,就是注入一个map类型,包含任意类型的键值对元素。 《props》使用该配置元素,注入一个集合,里面是string类型的键值对元素。 上述几种配置元素,你应该你能猜到,它们就是bean的xml配置文件中的元素,你可以使用或者来放任何 java.util.Collection 的实现类或者数组(array)。另外对于放入集合的元素可以是基本类型或者是另一个bean的引用。下面来看一个综合示例: package sirk_spring_tuto.demo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class CollectionsDemo { private List
前言 在java中,我想大家都用过内部类,今天要介绍的是spring中注入的内部Beans,与内部类类似,顾名思义,它就是被定义在某个Bean中的内部Bean。听起来有点奇怪,还是看个简单的配置实例就清楚了: 如上所示,如果在一个bean的或者元素标签内部定义的Bean则称为内部Bean。 用内部Bean改写上一篇的例子 由于大部分代码与上一篇一样,为了节省篇幅,这里只给出改动的部分,也就是xml配置文件: