分类 编程 下的文章

该绑定到哪个端口

这对于每一个编写服务器的程序员而言都是一个非常重要的考量。应该选择随机端口吗?该如何知道是否已经有其他的程序将某个端口宣为己有?

任何在 0~65535 之间的端口都可以使用,但是在选用之前别忘了一些重要的约定。

规则1: 不要使用 0~1024 之间的端口。

这些端口是作为熟知 (well-known)端口并保留给系统使用的。例如HTTP默认使用端口80, SMTP默认使用端口25,rsync默认使用端口873。绑定到这些端口通常需要root权限。

规则2: 不要使用 49000~65535 之间的端口。

这些都是临时 (ephemeral) 端口 。通常是由那些不需要运行在预定义端口,而只是需要一些端口作为临时之需的服务使用。它们也是后面所要讲到的连接协商 (connection negotiation) 过程的一部分。选择该范围内的端口可能会对一些用户造成麻烦。除此之外,1025~48999 之间端口的使用是一视同仁的。如果你打算选用其中的一个作为服务器端口,那你应该看一下 IANA 的注册列表,确保你的选择不会和其他流行的服务器冲突。

require 'socket'

# 该套接字将会绑定在环回接口,只侦听来自本地主机的客户端。
local_socket = Socket.new(:INET, :STREAM)
local_addr = Socket.pack_sockaddr_in(4481, '127.0.0.1')
local_socket.bind(local_addr)

# 该套接字将会绑定在所有已知的接口,侦听所有向其发送信息的客户端。
any_socket = Socket.new(:INET, :STREAM)
any_addr = Socket.pack_sockaddr_in(4481, '0.0.0.0')
any_socket.bind(any_addr)

# 该套接字试图绑定到一个未知的接口,结果导致Errno::EADDRNOTAVAIL。
error_socket = Socket.new(:INET, :STREAM)
error_addr = Socket.pack_sockaddr_in(4481, '1.2.3.4')
error_socket.bind(error_addr)

众所周知中文字体文件比较大,通常做法是将文字转换成图片来显示。但是当文案略微变换就必须生成新的图片。这样做不仅麻烦而且还很难自定义文字大小,通常伴随着图片压缩容易出现字体模糊的问题。

如果有一种方案既可以引用字体,又能使字体体积压缩,那无疑是最好的。那这就是本文所讲的字体压缩方案:

pip install fonttools
pyftsubset HanziPenSC-W3.ttf --text='abc这些文字可以用新字体' --output-file=HanziPenSC-W3-2.ttf

WPF和WinForm技术有什么区别?哪个更加有前景?

https://www.zhihu.com/question/36859063

wpf的底层是DirectX,意味着你的显示效果不仅可以更炫更酷,同时显卡(集显独显均可)提供的加速也不会拖累你的运行速度。

v2-d51859134e096e2ffa8bafede3d914c3_r.png

winform的底层是GDI/GDI+,除非你明确使用DX的接口,不然永远都是CPU在画图,效果没那么炫,而且无法显卡加速。

v2-f00831a14f767a26eb89e39da4e3e3c6_r.png

wpf的界面设计和逻辑设计可以分离,界面设计师可以利用blend自主设计好看的界面,而不是最终让程序员来实现那个复杂的动画或者设计。winform设计师最多拖一拖,而这往往不够用。

wpf对于数据逻辑、业务逻辑、显示逻辑进行了解耦和,可以让不同部门协同工作更舒服一些,winform多少有一些搅在一起。

目前做windows桌面应用程序,MFC、QT、C#哪个更好?

首先说Web,我们明确一点,当下的桌面软件项目,必须具备完整的Web能力(包括开发/部署/运行/测试等),直观的说就是你的软件中必须包含浏览器。尤其是企业软件,发展到后期,除了核心功能之外,必然附带大量的增删改查模块,这部分不用Web你会极其难受。有些人可能native用的挺熟练的,觉得不就是表格表单报表么?我用native一样堆出来——相信我,你在浪费生命。

Web必然入选,但是注意,Web入选不意味着electron入选。事实上如果不是互联网公司的项目,我不建议使用electron。一方面,传统公司不需要迭代那么快,他们前端力量也有限,出了问题解决不了;另一方面,哪怕是互联网项目,发展到后期,也不约而同地开始约束前端随意调用nodejs API的行为。

建议使用libcef提供Web能力,同时native封装有限的API供Web调用。这里我不推荐使用框架原生的webview,比如QtWebEngine,以及winform自带的WebBrowser组件,这些工具比较冷门,资料少,出了问题不好排查,而且浏览器内核版本也未必符合要求。

结论:libcef入选,electron淘汰,原生webview淘汰。

接下来考察C#和Qt,这两个技术各有支持者,不是非黑即白的关系。比如我看韦大的答案下面很多人在争论工控领域应该用Qt还是C#,其实国内工控领域的老大浙大中控,这两个技术都在使用。

我个人比较推荐Qt,极其强大,跨平台,可以用C++单一语言(调试成本低),还有一些很贴心的功能,比如基于qss的换肤。不要觉得换肤不重要,实际上做项目卖软件的公司经常遇到这样的需求,要么是甲方想用专有皮肤,要么是你接到的项目是OEM项目,中间商要求换肤。

但如果使用Qt,我不推荐使用Quick(Qml),太非主流,而且对比Web没什么优势。建议能用Web的模块就用Web,需要深度开发的模块使用QWidget配合OpenGL深度开发。

结论:Qt入选,但是Quick淘汰。

C#能有一席之地,主要是因为传统。有些领域长期以来就是使用C#开发,人才比较集中(C#人才确实比C++好招,而且便宜,也更不易跳槽),开发效率也确实高。如果没有跨平台诉求,也不是前瞻性很强的项目,可以考虑沿用C#(关于前瞻性,多说一句,新冷战都要来了,你确定你的项目不需要跨平台嘛)。

用了C#,还要选择是用winform还是用WPF,按理说这不该是个问题——无脑WPF就完事儿了,毕竟开发效率高,对于高分屏等新问题微软也会有相应的支持。但是什么问题只要涉及到“传统”,就说不清楚了,只能说如果是新产品,不考虑技术资产继承的话,建议WPF。

结论:WPF入选,winform你看着办。

综上,如果是我来作架构师,通常情况下我会选择Qt+libcef。兼顾强大功能与开发效率,同时Qt和Web前端都是前景光明的主流技术,社区力量强大,技术风险小。如果考虑到特定行业的技术积累(不光是你自己的积累,还有供应商等等)和人才招聘,可以考虑WPF+libcef。

作者:欲三更
链接:https://www.zhihu.com/question/402080800/answer/1308065143
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. r2 是比较早期的替代品,算是 request next 早期比较通用的产品,core 大约 3.17kb
  2. node-fetch 是仿造 fetch API 写的 NodeJS HTTP 客户端,如果你对 fetch 比较熟悉考虑这个,有点是一直在更新,启动堆栈差不多 20k 。大家比较熟就不多说了。
  3. axios 是浏览器与 NodeJS 兼容的,比较重,因为兼容了浏览器的代码。这部分代码在运行时也会进入堆栈,尽管不会执行,因为不管什么 module 都不能 tree shaking 编程式的分发的代码块。API 有些土里土气,属于简单易懂的状态型编程风格。
  4. bent 也是浏览器与 NodeJS 兼容的,但比较小巧 (意味着功能没有那么多)。API 只有一个函数,但是目前没有基线测试不知道性能如何。
  5. got 专业的 NodeJS HTTP 客户端。非常非常非常大。亮点之一就是支持 pagination 与一些编程式的 hook,社区中有非常非常非常多的示例教你如何使用它,毕竟用的人多。开发者也是知名的开源狂魔 sindresorhus (他维护了 1000+ 的开源仓库),算是比较值得信赖吧。
  6. superagent ,一个有意思的 HTTP 客户端库吧,用的链式 API 。也是兼容浏览器和 NodeJS 。优势是支持 HTTP2,具体可以看这个 PR。早期是你们熟知的 TJ 一个人在写,现在已经是组织在维护。(体积也很大)

总结一下,如果你喜欢小巧一些可以考虑 node-fetchbent,需要功能比较强大就是 gotsuperagent
另外给你们强烈推荐一个适用于微服务的 http-client: zeit-fetch,支持 DNS 缓存、重试和 keep-http-agent,如果你正在写微服务,可以试一试。

最后说一句题外话,现在 NodeJS 的 API 非常的友好,如果你只是一个简单的 request(特别是 get ) 不用库也就几行而已。

高阶函数:对传入的函数进行增强, 并返回一个添加了额外行为的新函数。

const HoC = Component => EnhancedComponent 

高阶组件其实就是函数,它接收组件作为参数,对组件进行增强后返回。

在使用PHP开发Web应用的中,很多的应用都会要求用户注册,而注册的时候就需要我们对用户的信息进行处理了,最常见的莫过于就是邮箱和密码了,本文意在讨论对密码的处理:也就是对密码的加密处理。

MD5

相信很多PHP开发者在最先接触PHP的时候,处理密码的首选加密函数可能就是MD5了,我当时就是这样的:

$password = md5($_POST["password"]);

上面这段代码是不是很熟悉?然而 MD5 的加密方式目前在PHP的江湖中貌似不太受欢迎了,因为它的加密算法实在是显得有点简单了,而且很多破解密码的站点都存放了很多经过MD5加密的密码字符串,所以这里我是非常不提倡还在单单使用 MD5 来加密用户的密码的。

SHA256 和 SHA512

其实跟前面的 MD5 同期的还有一个 SHA1 加密方式的,不过也是算法比较简单,所以这里就一笔带过吧。而这里即将要说到的SHA256SHA512 都是来自于 SHA2 家族的加密函数,看名字可能你就猜的出来了,这两个加密方式分别生成256和512比特长度的 hash 字串。

他们的使用方法如下:

<?php
$password = hash("sha256", $password);

PHP内置了 hash() 函数,你只需要将加密方式传给 hash() 函数就好了。你可以直接指明 sha256, sha512, md5, sha1 等加密方式。

盐值

在加密的过程,我们还有一个非常常见的小伙伴:盐值。对,我们在加密的时候其实会给加密的字符串添加一个额外的字符串,以达到提高一定安全的目的:

<?php
 
function generateHashWithSalt($password) {
    $intermediateSalt = md5(uniqid(rand(), true));
    $salt = substr($intermediateSalt, 0, 6);
    return hash("sha256", $password . $salt);
}

Bcrypt

如果让我来建议一种加密方式的话,Bcrypt 可能是我给你推荐的最低要求了,因为我会强烈推荐你后面会说到的 Hashing API,不过 Bcrypt 也不失为一种比较不错的加密方式了。

<?php
function generateHash($password) {
    if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
        $salt = '$2y$11$' . substr(md5(uniqid(rand(), true)), 0, 22);
        return crypt($password, $salt);
    }
}

Bcrypt 其实就是 Blowfishcrypt() 函数的结合,我们这里通过 CRYPT_BLOWFISH 判断 Blowfish 是否可用,然后像上面一样生成一个盐值,不过这里需要注意的是,crypt() 的盐值必须以 $2a$ 或者 $2y$ 开头,详细资料可以参考下面的链接:

http://www.php.net/security/crypt_blowfish.php

更多资料可以看这里:

http://php.net/manual/en/function.crypt.php

Password Hashing API

这里才是我们的重头戏,Password Hashing API是 PHP 5.5 之后才有的新特性,它主要是提供下面几个函数供我们使用:

password_hash() – 对密码加密.
password_verify() – 验证已经加密的密码,检验其hash字串是否一致.
password_needs_rehash() – 给密码重新加密.
password_get_info() – 返回加密算法的名称和一些相关信息.

虽然说crypt()函数在使用上已足够,但是password_hash()不仅可以使我们的代码更加简短,而且还在安全方面给了我们更好的保障,所以,现在PHP的官方都是推荐这种方式来加密用户的密码,很多流行的框架比如Laravel就是用的这种加密方式。

<?php
$hash = password_hash($passwod, PASSWORD_DEFAULT);

对,就是这么简单,一行代码,All done。

PASSWORD_DEFAULT 目前使用的就是Bcrypt,所以在上面我会说推荐这个,不过因为 Password Hashing API 做得更好了,我必须郑重地想你推荐 Password Hashing API。这里需要注意的是,如果你代码使用的都是 PASSWORD_DEFAULT 加密方式,那么在数据库的表中,password 字段就得设置超过60个字符长度,你也可以使用 PASSWORD_BCRYPT,这个时候,加密后字串总是60个字符长度。

这里使用 password_hash() 你完全可以不提供盐值(salt)和消耗值 (cost),你可以将后者理解为一种性能的消耗值,cost越大,加密算法越复杂,消耗的内存也就越大。当然,如果你需要指定对应的盐值和消耗值,你可以这样写:

<?php
$options = [
    'salt' => custom_function_for_salt(), //write your own code to generate a suitable salt
    'cost' => 12 // the default cost is 10
];
$hash = password_hash($password, PASSWORD_DEFAULT, $options);

密码加密过后,我们需要对密码进行验证,以此来判断用户输入的密码是否正确:

<?php
if (password_verify($password, $hash)) {
    // Pass
}
else {
    // Invalid
}

很简单的吧,直接使用 password_verify 就可以对我们之前加密过的字符串(存在数据库中)进行验证了。

然而,如果有时候我们需要更改我们的加密方式,如某一天我们突然想更换一下盐值或者提高一下消耗值,我们这时候就要使用到password_needs_rehash()函数了:

<?php
if (password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12])) {
    // cost change to 12
    $hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
 
    // don't forget to store the new hash!
}

只有这样,PHP的 Password Hashing API 才会知道我们重现更换了加密方式,这样的主要目的就是为了后面的密码验证。

简单地说一下 password_get_info(),这个函数一般可以看到下面三个信息:

algo – 算法实例
algoName – 算法名字
options – 加密时候的可选参数

所以,现在就开始用 PHP 5.5 吧,别再纠结低版本了。


本文转载来自:codecasts
原作者:JellyBool

一个语言的“入流”,和是不是英文关键字无关,而是和这种语言进入某一子行业的契机有关。

比如 C 语言的出现解决了系统程序源代码的可移植性问题,使得更多的小型机可以在更短时间内移植 Unix 操作系统。所以 Unix 选择用 C 重写,而 C 成为编写操作系统和实现 TCP/IP 协议的首选语言。今天众多设备上的各类操作系统,TCP/IP 协议实现都要归功于 C 语言;

比如 C++ 的出现适逢图形界面的兴起,需要面向对象技术对图形编程框架建模,同时又要提供能运行于微型处理器的高性能;

Java 的流行适逢企业的信息化浪潮,大量的企业级的复杂任务,需要更短的时间内,写出更大规模的程序。所以 Java 通过更多的权限关键字,垃圾回收等等,带来的是整个行业生产力的提升;

PHP 的流行是因为行业需要快速的编写动态 Web 服务端程序。

而 Python 进入 Web 开发是因为如今 Web 应用日渐复杂,需要更多的交互技术(比如用于实时的长链接)和使用更多的第三方库(必须一些自然语言处理、计算机视觉和机器学习任务)。

以上这些语言如果不是在第一时间出现解决了行业急需解决的问题,可能以后再也没有机会“入流”。再回来看“易语言”,中文关键字解决的是没有一点英文基础的初学者的入门问题。但这个问题不是行业痛点,因为具备基本英文能力的程序员从来就不缺,将来更不可能缺。因此,没有一个行业急需“易语言”解决没有英文基础的初学者入门的问题,“易语言”凭借这个优势就没有任何的“入流”机会。相反,由于面试者普遍看中英文文档、论文的阅读能力,“易语言”反倒会帮助企业剃掉那些没有英文基础的应聘者。

作者:安江泽
链接:https://www.zhihu.com/question/19770358/answer/17497656
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

The easiest way I've found to install pip3 (for python3.x packages) on CentOS 7 is:

$ sudo yum install python34-setuptools
$ sudo easy_install-3.4 pip

You'll need to have the EPEL repository enabled before hand, of course.

You should now be able to run commands like the following to install packages for python3.x:

$ pip3 install foo

axios({
  method: 'get',
  url: '/reports/interval-dates',
  responseType: 'arraybuffer',
  data: dates
}).then(function(response) {
  let blob = new Blob([response.data], { type: 'application/pdf' })
  let link = document.createElement('a')
  link.href = window.URL.createObjectURL(blob)
  link.download = 'Report.pdf'
  link.click()
})