收藏python包安装的一个源

pip的很多源都被屏蔽了,或者重定向了,或者要求必须要求https之类的,收藏一个 比较快的源

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple + 包名

阅读全文 »


go中变量函数方法被导出与首字母大写

最近在写go相关代码,由于基础知识不够牢靠,被个小问题折腾了好久

func (p *Student) FirstName() string {
	return p.firstName
}

在A包中定义了一个方法firstName(), 在B包中引入这个方法,一直提示找不到该方法, 是因为在go中需要将方法名的首字母改成大写FirstName(), 才标识该方法可以被导出。

阅读全文 »


为什么socket server端需要bind, client端一般不需要bind

bind() 函数的定义与作用—— 将本地地址与某一套接口捆绑。本函数适用于未连接的数据报或流类套接口,在connect()或listen()调用前使用。 当用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/端口号)。

服务端——

服务端进程bind端口:基本是必须要做的事情,比如一个服务器启动时(比如freebsd),它会一个一个的捆绑众所周知的端口来提供服务,同样,如果bind了一个端口就表示我这个服务器会在这个端口提供一些“特殊服务”。 服务端进程bind IP地址:目的是限制了服务端进程创建的socket只接受那些目的地为此IP地址的客户链接;

但是经常看见一些server端的代码是这么写的(没有明确写明bind 的IP):

serv.sin_addr.s_addr=htonl(INADDR_ANY);

这种设定是因为该server可能有多个网卡(多个IP),但不确定client会从哪个网卡连接进来。这么设置可以使bind IP这个过程推迟,直到client端与server建立连接后,server才确定bind 哪个IP.

客户端——

socket_connect($socket, $host, $port);

TCP socket客户端通过调用Connect函数来连接server端,Connect()函数的第二个参数就是server端的地址信息,因为这种情况下只需知道server端 的地址,而客户通过哪个端口与服务器建立连接并不重要,socket执行体为你的程序自动选择一个未被占用的端口,并通知你的程序数据什么时候打开端口,因此无须调用bind()。(当然也有特殊情况,linux系统中rlogin命令应当调用bind函数绑定一个未用的保留端口号,还有当客户端需要用指定的网络设备接口和端口号进行通信等等)

客户端bind了地址可能带来的问题: 如果在client端的程序里,bind()了某个端口(比如 3456)。首先,得考虑这个端口是否被其他的程序占用了(增加了实现的难度和麻烦)。第二,如果client端是hard code了bind这么一个端口(3456),那么在这台电脑上,就只能运行一个客户端,因为同一个端口只能给一个socket使用。

总结:

bind地址的意义在于,可以提前确定端口号——比如:用于浏览网页服务的80端口,用于FTP服务的21端口等。server有这个需求,但是client基本没这个需求。 其他:

使用bind函数时,通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。 Bind()函数在成功被调用时返回0;出现错误时返回”-1”并将errno置为相应的错误号。

需要注意的是,在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。

参考:http://blog.chinaunix.net/uid-23193900-id-3199173.html

阅读全文 »


yii框架路由的实现

yii框架中路由的实现核心代码

<?php

if (PHP_SAPI != 'cli') {
    exit('Please run it in terminal!');
}
if ($argc < 3) {
    exit('At least 2 arguments needed!');
}
$controller = ucfirst($argv[1]) . 'Controller';
$action = 'action' . ucfirst($argv[2]);
// 检查类是否存在
if (!class_exists($controller)) {
    exit("Class $controller does not existed!");
}
// 获取类的反射
$reflector = new ReflectionClass($controller);
// 检查方法是否存在
if (!$reflector->hasMethod($action)) {
    exit("Method $action does not existed!");
}
// 取类的构造函数,返回的是ReflectionMethod对象
$constructor = $reflector->getConstructor();
// 取构造函数的参数
$parameters = $constructor->getParameters();
// 遍历参数
foreach ($parameters as $key => $parameter) {
    // 获取参数声明的类
    $injector = new ReflectionClass($parameter->getClass()->name);
    // 实例化参数声明类并填入参数列表
    $parameters[$key] = $injector->newInstance();
}
// 使用参数列表实例 controller 类
$instance = $reflector->newInstanceArgs($parameters);
// 执行
$instance->$action();

class HelloController
{
    private $model;
    public function __construct(TestModel $model)
    {
        $this->model = $model;
    }
    public function actionWorld()
    {
        echo $this->model->property, PHP_EOL;
    }
}
class TestModel
{
    public $property = 'property';
}

阅读全文 »


socket端口复用

socket编程中的端口复用问题

一般来讲,在我们写一个server的时候,会用到SO_REUSEADDR,因为,当server正常或者异常重启的时候, 可能server的一些子进程或者client端的一些进程还在工作,也或者一些连接还处于time_wait状态,而且time_wait状态的时间一般比较长, 如果没有SO_REUSEADDR,则会因为端口被占用而bind失败,无法启动server,实例如下:

<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if (!is_resource($socket)) {
    echo 'Unable to create socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
}

if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
    echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
}

if (!socket_bind($socket, '127.0.0.1', 1223)) {
    echo 'Unable to bind socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
}

$rval = socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR);

if ($rval === false) {
    echo 'Unable to get socket option: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else if ($rval !== 0) {
    echo 'SO_REUSEADDR is set on socket !' . PHP_EOL;
}

注意: 端口被占用后,不是listen是否能够成功,主要是bind能否成功,bind会报端口被占用的错误。

阅读全文 »


redis jemalloc报错

centos6.5安装redis报错,报错信息为

zmalloc.h:50:31: 错误:jemalloc/jemalloc.h:没有那个文件或目录
zmalloc.h:55:2: 错误:#error "Newer version of jemalloc required"

后来查看资料是因为: 说关于分配器allocator, 如果有MALLOC 这个 环境变量, 会有用这个环境变量的 去建立Redis。 而且libc 并不是默认的 分配器, 默认的是 jemalloc, 因为 jemalloc 被证明 有更少的 fragmentation problems 比libc。 但是如果你又没有jemalloc 而只有 libc 当然 make 出错

解决办法, make的时候加参数

make MALLOC=libc

阅读全文 »