找到归档 2014-02 的文章 8 篇.


发送邮件提示 551 User not local; please try 错误信息的原因及解决

Posted on 2014-02-28 16:49:03 network

在此博客运行的云主机上,使用SMTP客户端发送邮件到国内的SMTP服务器,报如下错误:

2014/02/28 16:17:29 551 User not local; please try <forward-path>

说明:这个错误和邮件内容、标题等完全没有关系,而是GFW的原因。Google到如下答案:

中国政府的国家防火墙(GFW,又名`金盾工程`)做了过滤的原因,它(金盾工程)定义了大陆的IP连接到大陆以外(如香港、台湾、欧洲等)的邮件服务器是不可以自己发邮件给自己的!只要大陆所在客户端用大陆的IP发送邮件,马上就会提示551 User not local; please try这样的错误信息!

本人实际遇到的问题,是在国外的主机上使用大陆的邮件服务器,发送邮件给自己。应该也是GFW在作怪。

解决办法有两个:

  1. 使用VPN发送邮件
  2. 使用国外的SMTP服务器,发送邮件到国内的SMTP服务器

在使用了Gmail的SMTP服务器发送邮件到QQ的SMTP邮件服务器之后,错误不再出现。


Golang中字符串的一个坑

Posted on 2014-02-23 13:41:38 golang

在C语言中,字符串的内存模型定义为以NUL(\x0)结尾的字节数组。这是为大家所熟知的。

但是在Golang中并不是如此,Golang中的字符串abcabc\x0\x0并不相当,所以说Golang明确规定了字符串的长度,而不是以\x0为结尾来判断的。

下面看示例代码:

package main

import (
    "fmt"
    "os"
)

func main() {
    var a[5]byte = [5]byte{'a','b','c'}
    var b[]byte = []byte{'a','b','c'}

    fmt.Printf("len(a): %d, %q\n", len(a), a)
    fmt.Printf("len(b): %d, %q\n", len(b), b)

    slice_a := a[:]
    str_a := string(slice_a)
    str_b := string(b)
    fmt.Printf("len(str_a): %d, %q:%s\n", len(str_a), str_a, str_a)
    fmt.Printf("len(str_b): %d, %q:%s\n", len(str_b), str_b, str_b)

    if str_a == str_b {
        fmt.Println("str_a == str_b")
    } else {
        fmt.Println("str_a != str_b")
    }

    file, err := os.Create(str_a)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(file)
}

代码输出为:

len(a): 5, "abc\x00\x00"
len(b): 3, "abc"
len(str_a): 5, "abc\x00\x00":abc
len(str_b): 3, "abc":abc
str_a != str_b

open abc: invalid argument
<nil>

数组a长度为5,最后两个字节为\x00。切片b长度为3,有效内容为abc。 分别将a和b转换为string类型后,数组a中包含的\x00也被保留下来,所以在对比时,这两者的长度不可能相等的。

当然这还不是最关键的,问题处在当用str_a作为文件名创建文件时file, err := os.Create(str_a),系统会报错:open abc: invalid argument。说明这不是一个有效的路径名称。

Golang是一种强类的语言,对于数组来说[3]byte[5]byte并不是同一个类型,不能通用。 当然,数组和切片也更不可能是同一个类型。

解决办法是,迭代数组中的字节,跳过为0的字节:

func GetValidByte(src []byte) []byte {
    var str_buf []byte
    for _, v := range src {
        if v != 0 {
            str_buf = append(str_buf, v)
        }
    }
    return str_buf
}

浅谈TCP/IP网络编程中socket的行为

Posted on 2014-02-22 07:59:54 network

摘要:

我认为,想要熟练掌握Linux下的TCP/IP网络编程,至少有三个层面的知识需要熟悉:

1. TCP/IP协议(如连接的建立和终止、重传和确认、滑动窗口和拥塞控制等等)

2. Socket I/O系统调用(重点如read/write),这是TCP/IP协议在应用层表现出来的行为。

3. 编写Performant, Scalable的服务器程序。包括多线程、IO Multiplexing、非阻塞、异步等各种技术。

关于TCP/IP协议,建议参考Richard Stevens的《TCP/IP Illustrated,vol1》(TCP/IP详解卷1)。

关于第二层面,依然建议Richard Stevens的《Unix network proggramming,vol1》(Unix网络编程卷1),这两本书公认是Unix网络编程的圣经。

至于第三个层面,UNP的书中有所提及,也有著名的C10K问题,业界也有各种各样的框架和解决方案,本人才疏学浅,在这里就不一一敷述。

本文的重点在于第二个层面,主要总结一下Linux下TCP/IP网络编程中的read/write系统调用的行为,知识来源于自己网络编程的粗浅经验和对《Unix网络编程卷1》相关章节的总结。由于本人接触Linux下网络编程时间不长,错误和疏漏再所难免,望看官不吝赐教。

阅读全文

Gevent的hub剖析

Posted on 2014-02-13 16:41:10 gevent

摘要:
  • hub是gevent中核心,依靠libev这个事件库,来调度所有的greenlet。

  • hub也是一个greenlet,就是所谓的’main’ greenlet。

  • hub会首先启动,然后马上启动事件循环。也就是libev的loop。

  • hub对应到实际的代码就是hub.py,其中最关键的是Hub类。

  • hub保存在线程的本地数据中,所以说每个线程中只存在一个’main’ hub。

  • 从main greenlet切换到普通greenlet之后,main greenlet是停止执行的。greenlet是安排合理的串行,从而看起来像是并行。

  • 切换到main greenlet是指首先切换到hub.wait,然后在greenlet.so中执行真正的greenlet切换。 即切换到需要运行的那个greenlet。

  • 所谓的’由hub决定运行哪个greenlet’,实际上是loop检测到greenlet感兴趣的事件后,首先切换到hub,再由hub.switch切换到发生事件的那个greenlet。主导整个过程的是libev的loop。

阅读全文

Greenlet简介

Posted on 2014-02-12 08:11:23 python

摘要:

一个 greenlet 是一个很小的独立微线程。可以把它想像成一个堆栈帧,栈底是初始调用,而栈顶是当前greenlet的暂停位置。你使用greenlet创建一堆这样的堆 栈,然后在他们之间跳转执行。跳转不是绝对的:一个greenlet必须选择跳转到选择好的另一个greenlet,这会让前一个挂起,而后一个恢复。两 个greenlet之间的跳转称为 切换(switch) 。

当你创建一个greenlet,它得到一个初始化过的空堆栈;当你第一次切换到它,他会启动指定的函数,然后切换跳出greenlet。当最终栈底 函数结束时,greenlet的堆栈又编程空的了,而greenlet也就死掉了。greenlet也会因为一个未捕捉的异常死掉。

阅读全文

libev简介

Posted on 2014-02-12 07:36:22 c

摘要:

libev是Marc Lehmann用C写的高性能事件循环库。通过libev,可以灵活地把各种事件组织管理起来,如:时钟、io、信号等。libev在业界内也是广受好评,不少项目都采用它来做底层的事件循环。

阅读全文

fcntl的close-on-exec标志

Posted on 2014-02-10 09:30:13 c

摘要:

每个文件描述符都有一个close-on-exec标志。默认情况下,这个标志最后一位被设置为 0。这个标志符的具体作用在于当开辟其他进程调用exec()族函数时,在调用exec函数之前为exec族函数释放对应的文件描述符。

阅读全文

Golang的RESTful框架

Posted on 2014-02-10 08:43:22 golang

摘要:

Golang有自带的net/rpc和net/rpc/jsonrpc,前者是基于Gob编码协议的RPC,后者在前者基础上使用JSON编码。

在Python的世界,RESTful的框架比比皆是。由于Golang标准库没有自带,但有许多优秀的第三方库,例如下面要介绍的这个库,go-json-rest.

阅读全文