","post_title":"简单理解tcp","post_excerpt":"","post_name":"tcp","post_modified_gmt":"2017-09-23T07:29:09.000Z"},{"ID":520,"post_content":"1、概念理解\r\n\r\n高大上的概念讲不来,讲下我自己对docker两个重要镜像、容器的通俗理解:\r\n\r\n什么是镜像,镜像是docker包\r\n什么是容器,容器根据docker包运行的实例\r\n\r\n2、如何或者docker镜像\r\n\r\n使用docker pull从docker的镜像市场下载(https://hub.docker.com),例如想要用到mysql的服务,那么完整的命令是:\r\n\r\n
docker pull mysql\r\n\r\n3、如何创建docker容器\r\n\r\n
docker run --name first-mysql -p 3306:3306 -v ~/Documents/docker/mysql/data:/var/lib/mysql -v ~/Documents/docker/mysql/conf/my.cnf:/etc/mysql/my.cnf -e MYSQL\\_ROOT\\_PASSWORD=123456 -d mysql\r\n\r\n
#### 说明:\r\n\r\n-d : --detach,后台运行。\r\n--name : 为你的镜像创建一个别名,该别名用于更好操作。\r\n-p : 映射端口,一般我们会将默认端口进行更改,避免与本机的mysql端口冲突,如果你宿主机有mysql,请更改端口,如 -p 33060:3306。\r\n-e : 环境变量。为mysql的root用户设置密码为123456。\r\n-v : 指定数据卷,意思就是将mysql容器中的/var/lib/mysql(这个是数据库所有数据信息文件)映射到宿主机/data/mysql里面。\r\n\r\n4、如何在容器做后台运行后进入运行的容器\r\n\r\n这个动作就跟我们装完系统,系统启动后,我们要进入系统玩耍一个意思\r\n\r\n
docker exec -t -i first-mysql /bin/bash\r\n\r\n
#### 说明:\r\n\r\n-i : --interactive,交互界面。\r\n-t : --tty,伪终端界面。\r\n/bin/bash: 运行bash shell\r\n\r\n5、如何不让容器进入后台运行,而是直接做前台跑\r\n\r\n这个动作一般是临时跑容器,比如自己创建镜像、封装镜像\r\n\r\n
docker run -t -i ubuntu /bin/bash\r\n\r\n
#### 说明:\r\n\r\n-i : --interactive,交互界面。\r\n-t : --tty,伪终端界面。\r\nubuntu: 镜像\r\n/bin/bash: 运行bash shell\r\n\r\n6、如何创建新镜像\r\n\r\n
docker build -t mysql.\r\n\r\n7、删除镜像\r\n\r\n
docker rmi\r\n\r\n8、删除容器\r\n\r\n
docker rm\r\n\r\n9、查看运行的容器\r\n\r\n
docker ps -a\r\n\r\n10、使用 docker-compose.yml 生成容器\r\n\r\n生成管理容器方便的工具,使用前需要安装docker-compose,除了docker-compose还有dockerfile可以管理容器\r\n\r\n
docker-compose up -d\r\n\r\n11、私有化 docker hub\r\n\r\n
# 注册\r\ndocker run -p 5000:5000 registry\r\n\r\n# 打tag\r\ndocker tag b832n2b87 192.168.1.1:5000/vim #docker tag $ID $IP:$port/$name\r\n\r\n# 上传\r\ndocker push 192.168.1.1:5000/vim\r\n\r\n# 拉取\r\ndocker pull 192.168.1.1:5000/vim\r\n","post_title":"docker学习笔记(待完善)","post_excerpt":"","post_name":"docker_notes","post_modified_gmt":"2017-09-13T06:28:00.000Z"},{"ID":516,"post_content":"react全家桶最陡峭的redux这部分状态管理,这部分输出了几个比较晦涩的概念,如果没在实际项目应用,很难理解,而且讲真用过vue的同学都会被vue-cli的方便给吸引,官方也出了vuex的实例很容上手,还有ng2的ng-cli也不错,但是react的create-react-app的使用并不是太美,像是redux、flux之类的东西要自己搭建,写法多样,上手起来总是不是太顺手。\r\n\r\n当然上面说的可能是我程度不够,之前做公司搭建的一个react的脚手架并不是太顺利,可以说遇到蛮多坑的,照搬了vue的那套手脚架,用起来还是OK的,但就是有些繁琐,这里贴一下项目地址:https://github.com/zkeyword/react-demo。\r\n\r\n说起来和dva的故事,怎么说呢,算我见识浅薄吧,当场搭完上面的脚手架之后,看过一部分文档,耐心不够,因为dva又引入了model、service,而model又有namespace、reducers、effects、subscriptions等概念,看了有点发怵,本来redux已经绕晕我了,项目就没用到dva的架构,后面跳槽之后重新了解了dva,发现dva的团队的文档还是蛮细的,让我找到了当初是用vue-cli的那种感觉了,虽然有一些版本更新的诟病,但是最近发布的dva 2.0,今天刚刚试用了一下还是不错的。\r\n\r\n目前,正在使用dva1.x开发项目,用起来还是比较顺畅的,由于dva-cli没有支持stylus,我并没有是用dva-cli搭建项目,而是具有普通的webpack搭建的架子:https://github.com/zkeyword/dynamax-react-scaffold-dva,下一步的计划是使用dva-cli提供的自定义webpack配置支持stylus并更新到dva2.0。\r\n\r\n接下来讲讲dva的一些技术要点,总体来说react全家桶最绕的地方是redux这部分,redux跟着教程走一波,也不一定能搞懂,还有对于团队的小伙伴,程度是不一样的,要跟上解释起来也是蛮麻烦。而dva则做redux之上封装了一层,我觉得核心部分就是model这块,简化的曲线的效果特别明显。\r\n\r\nmodel由namespace、state、reducers、effects、subscriptions组成:\r\n
namespace 标识model,后期可用namespace的名称调用model\r\n\r\nstate 默认数据\r\n\r\nreducers action的集合,唯一能修改state的东西\r\n\r\neffects 可以理解为方法的集合体,这里定义的方法可以供components、model等地方使用,只要dispatch一下就可以改变state\r\n\r\nsubscriptions 这里可以监听路由的变化、键盘事件等\r\n代码的基本流向是:\r\n
index.js(入口文件) => router.js => model(绑定)\r\n => components => dispatch => effects => reducers => state\r\n其中effects的方法有call、select、put三个参数:\r\n
call 是一些异步的操作,如service的ajax、promise操作等\r\n\r\nselect 拥有调用全局所有model的能力\r\n\r\nput 用于触发action,如reducers\r\n\r\n以上只是一些我get到的点,若要上手还是参照官方的代码git clone个下来溜溜。\r\n\r\n使用dva的话,其实有些不好的就是常用的react生命周期的api,用的少了,这就跟当场用jQuery一样,jQuery用的多了,原生的js很多就写不出来了。不过项目大了,用dva来组织代码结构,还是比较好维护的,由于上手react不久,深度不够,不喜勿喷。","post_title":"用dvajs简化react的学习曲线","post_excerpt":"","post_name":"dvajs-react","post_modified_gmt":"2017-09-12T07:21:54.000Z"},{"ID":513,"post_content":"还有些问题但基本能用:\r\n\r\n
import socket\r\nimport threading\r\nimport signal\r\nimport sys\r\n\r\n\r\nconfig = {\r\n \"HOST_NAME\" : \"0.0.0.0\",\r\n \"BIND_PORT\" : 8899,\r\n \"MAX_REQUEST_LEN\" : 1024,\r\n \"CONNECTION_TIMEOUT\" : 5\r\n }\r\n\r\n\r\nclass Server:\r\n\r\n def __init__(self, config):\r\n signal.signal(signal.SIGINT, self.shutdown)\r\n self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r\n self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\r\n self.serverSocket.bind((config['HOST_NAME'], config['BIND_PORT']))\r\n self.serverSocket.listen(10) # become a server socket\r\n self.__clients = {}\r\n\r\n\r\n def listenForClient(self):\r\n while True:\r\n (clientSocket, client_address) = self.serverSocket.accept()\r\n d = threading.Thread(name=self._getClientName(client_address), target=self.proxy_thread, args=(clientSocket, client_address))\r\n d.setDaemon(True)\r\n d.start()\r\n self.shutdown(0,0)\r\n\r\n\r\n def proxy_thread(self, conn, client_addr):\r\n\r\n request = conn.recv(config['MAX_REQUEST_LEN'])\r\n first_line = request.split('\\n')[0] \r\n url = first_line.split(' ')[1] \r\n\r\n # find the webserver and port\r\n http_pos = url.find(\"://\") # find pos of ://\r\n if (http_pos==-1):\r\n temp = url\r\n else:\r\n temp = url[(http_pos+3):] \r\n\r\n port_pos = temp.find(\":\") \r\n\r\n # find end of web server\r\n webserver_pos = temp.find(\"/\")\r\n if webserver_pos == -1:\r\n webserver_pos = len(temp)\r\n\r\n webserver = \"\"\r\n port = -1\r\n if (port_pos==-1 or webserver_pos < port_pos): \r\n port = 80\r\n webserver = temp[:webserver_pos]\r\n else: \r\n port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1])\r\n webserver = temp[:port_pos]\r\n\r\n try:\r\n # create a socket to connect to the web server\r\n s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r\n s.settimeout(config['CONNECTION_TIMEOUT'])\r\n s.connect((webserver, port))\r\n s.sendall(request) \r\n\r\n while 1:\r\n data = s.recv(config['MAX_REQUEST_LEN']) \r\n if (len(data) > 0):\r\n conn.send(data) \r\n else:\r\n break\r\n s.close()\r\n conn.close()\r\n except socket.error as error_msg:\r\n print 'ERROR: ',client_addr,error_msg\r\n if s:\r\n s.close()\r\n if conn:\r\n conn.close()\r\n\r\n\r\n def _getClientName(self, cli_addr):\r\n return \"Client\"\r\n\r\n\r\n def shutdown(self, signum, frame):\r\n self.serverSocket.close()\r\n sys.exit(0)\r\n\r\n\r\nif __name__ == \"__main__\":\r\n server = Server(config)\r\n server.listenForClient()\r\n","post_title":"用python写一个正向代理服务","post_excerpt":"用python写一个正向代理服务,直接使用8899端口就能使用","post_name":"python_proxy","post_modified_gmt":"2017-08-08T19:32:20.000Z"},{"ID":511,"post_content":"
import os\r\nimport time\r\nimport socket\r\nimport urllib\r\nimport urllib2\r\n# from subprocess import call\r\n\r\nimport shlex\r\nimport datetime\r\nimport subprocess\r\n\r\nsocket.setdefaulttimeout(180)\r\n\r\napiUrl = 'http://xxx.com/push/ip'\r\ntoken = 'bd934b846164f97a1f15bca8d64cec51'\r\nvpn = '1'\r\ng_adsl_account = {\"name\": \"adsl\",\r\n \"username\": \"adsl账号\",\r\n \"password\": \"adsl密码\"}\r\n\r\n\r\nclass Adsl(object):\r\n def __init__(self):\r\n self.name = g_adsl_account[\"name\"]\r\n self.username = g_adsl_account[\"username\"]\r\n self.password = g_adsl_account[\"password\"]\r\n\r\n def connect(self):\r\n try:\r\n cmd_str = \"rasdial %s %s %s\" % (\r\n self.name, self.username, self.password)\r\n self.execute_command(cmd_str, None, 10)\r\n # stauts = os.system(cmd_str)\r\n # print os.popen(cmd_str).read()\r\n # print os.popen('rasdial').read()\r\n # call(cmd_str)\r\n localtime = time.strftime(\r\n \"%Y-%m-%d %H:%M:%S\", time.localtime(time.time()))\r\n print \"status: connect; current: %s\" % localtime\r\n time.sleep(5)\r\n except:\r\n self.reconnect()\r\n\r\n def disconnect(self):\r\n self.execute_command(\"taskkill /F /IM rasdial.exe\", None, 10)\r\n cmd_str = \"rasdial %s /disconnect\" % self.name\r\n self.execute_command(cmd_str, None, 10)\r\n # os.system(cmd_str)\r\n # call(cmd_str)\r\n localtime = time.strftime(\r\n \"%Y-%m-%d %H:%M:%S\", time.localtime(time.time()))\r\n print \"status: disconnect; current: %s\" % localtime\r\n time.sleep(5)\r\n\r\n def reconnect(self):\r\n self.disconnect()\r\n self.connect()\r\n self.handleIp()\r\n\r\n def handleIp(self):\r\n localtime = time.strftime(\r\n \"%Y-%m-%d %H:%M:%S\", time.localtime(time.time()))\r\n localIPList = socket.gethostbyname_ex(socket.gethostname())\r\n ip = localIPList[2][-1]\r\n print \"get Ip: %s; current: %s\" % (ip, localtime)\r\n try:\r\n values = {'ip': ip, 'access_token': token, 'vpn': vpn}\r\n data = urllib.urlencode(values)\r\n req = urllib2.Request(apiUrl, data)\r\n response = urllib2.urlopen(req, timeout=180)\r\n status = response.read().decode('utf-8', 'ignore')\r\n self.getStatus(status)\r\n except:\r\n self.getStatus(0)\r\n\r\n def getStatus(self, status):\r\n localtime = time.strftime(\r\n \"%Y-%m-%d %H:%M:%S\", time.localtime(time.time()))\r\n print \"status: %s; current: %s\" % (status, localtime)\r\n if status == '1':\r\n print 'sleep: 180 second'\r\n time.sleep(180)\r\n self.reconnect()\r\n else:\r\n print 'status: reconnect'\r\n self.reconnect()\r\n\r\n def execute_command(self, cmdstring, cwd=None, timeout=None, shell=False):\r\n if shell:\r\n cmdstring_list = cmdstring\r\n else:\r\n cmdstring_list = shlex.split(cmdstring)\r\n if timeout:\r\n end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)\r\n sub = subprocess.Popen(cmdstring_list, cwd=cwd,\r\n stdin=subprocess.PIPE, shell=shell, bufsize=4096)\r\n while sub.poll() is None:\r\n time.sleep(0.1)\r\n if timeout:\r\n if end_time <= datetime.datetime.now():\r\n raise Exception('Timeout: %s' % cmdstring)\r\n\r\n return str(sub.returncode)\r\n\r\n\r\nadsl = Adsl()\r\nadsl.reconnect()\r\n\r\n","post_title":"用python写一个自动adsl拨号","post_excerpt":"用python实现adsl自动拨号,获取ip后自动推送到目标地址。","post_name":"python_adsl","post_modified_gmt":"2017-08-08T19:29:10.000Z"},{"ID":506,"post_content":"
const Canvas = process.env.NODE_ENV === 'development' ? require('canvas-prebuilt') : require('canvas')\r\n\r\n当然canvas-prebuilt并不是太好的解决方式,毕竟如果环境不一样依赖还不一样,这个可能有隐形的bug,实现起来还说尽量统一,避免生成环境和开发环境的依赖一致。\r\n\r\n参考资料:\r\n\r\nhttps://github.com/Automattic/node-canvas\r\nhttps://github.com/chearon/node-canvas-prebuilt","post_title":"用canvas-prebuilt模块解决canvas模块做windows安装不上的问题","post_excerpt":"","post_name":"node-canvas-prebuilt","post_modified_gmt":"2017-05-02T07:03:47.000Z"},{"ID":498,"post_content":"在写这边文章的前面我们来看段代码:\r\n
app.use((req, res, next) => {\r\n /*\r\n *\r\n * ... 中间件代码\r\n *\r\n */ \r\n next()\r\n})\r\n上面,这段是一个典型的express中间代码,那为什么需要中间件?中间件是什么?node社区上有一张很典型的express或者koa的洋葱模型:\r\n
const rp = require('request-promise')\r\nconst logger = require('../lib/logger.lib')\r\n\r\nexports.postHaddle = (url, req, res, next) => {\r\n let sn = Number(new Date())\r\n let body = {\r\n sn,\r\n openId: req.session.openId,\r\n data: req.body\r\n }\r\n let options = {\r\n method: 'POST',\r\n json: true,\r\n uri: url,\r\n body\r\n }\r\n return rp(options)\r\n .then(data => {\r\n return data\r\n })\r\n .catch(err => {\r\n logger.api().error(`name: ${err.name}, message: ${err.message}, url: ${err.options.uri}`)\r\n console.error(err)\r\n if (next) {\r\n return next()\r\n }\r\n res && res.json({ sn, code: -1, msg: '接口访问出错', data: body })\r\n })\r\n}","post_title":"用request-promise模块使接口请求变更简单","post_excerpt":"","post_name":"request-promise","post_modified_gmt":"2017-04-26T06:16:48.000Z"},{"ID":491,"post_content":"由于项目的底层架构是java,所以一些基础服务是有java搭建的,其中登录模块是由java cas搭建,这样可以做到多个系统单点登录,其中,我做的一个node项目是做这些系统中的一个,所以我引入了node的cas模块,使用时直接用npm安装就可以了:\r\n
npm i cas\r\n使用的地方直接引入,当然你可以像我一样做成一个可以复用的模块\r\n
const CAS = require('cas')\r\nconst urlFix = require('./api.config')\r\n\r\nmodule.exports = new CAS({\r\n base_url: 'http://192.168.250.173/cas', // cas服务端\r\n service: 'http://192.168.250.172/', // cas客服端也就是node端,其中,请加入 / (有坑)\r\n version: 2.0\r\n})\r\n\r\n\r\n然后,在路由上需要认证的地方,要获取cas的ticket,我是把这个认证做成一个路由的中间件,比如:\r\n
app.use('/login', auth, require('./login'))\r\nauth,就是写获取ticket和校验ticker的地方,当然,也可以直接用做路由上,\r\n
router.get('/post', (req, res) => {\r\n let ticket = req.param('ticket')\r\n cas.validate(ticket, (err, status, username, obj) => {\r\n if (err) {\r\n console.error(`ticket error:${err}`)\r\n res.redirect('/500')\r\n }\r\n res.send({ code: 1, msg: '登录成功' })\r\n })\r\n})\r\n\r\n\r\n详细文档可以看下,cas模块作者的文档:https://github.com/kcbanner/node-cas","post_title":"使用cas模块搭建cas的node client","post_excerpt":"","post_name":"node-cas","post_modified_gmt":"2017-04-25T07:06:38.000Z"}],"pageIndex":1,"pageSize":10,"total":140}}