linux mail

linux mail 命令参数:

使用mail发邮件时,必须先将sendmail服务启动。
mail –s “邮件主题” –c ”抄送地址” –b “密送地址” -f 发送人邮件地址 –F 发件人姓名 < 要发送的邮件内容

Usage: mail [-BDFintv~] [-s subject] [-a attachment ] [-c cc-addr] [-b bcc-addr]
[-r from-addr] [-h hops] [-A account] [-R reply-addr] to-addr …
mail [-BDeHiInNRv~] [-T name] [-A account] -f [name]
mail [-BDeinNRv~] [-A account] [-u user]

三种常用格式发信:
  mail -s test yangfang@fudan.edu.cn #第一种方法,你可以把当前shell当成编辑器来用,编辑完内容后Ctrl-D结束
  echo “mail content”|mail -s test yangfang@fudan.edu.cn #第二种方法,我用的最多,可能是喜欢管道的缘故吧
  mail -s test yangfang@fudan.edu.cn < file #第三种方法,以file的内容为邮件内容发信

指定特定的发送人:
$ mail -s "just a test" -r 发送人地址 收信人邮箱地址 < 要发送的邮件内容文件

效果是: 信件内容将发送给 收信人邮箱,显示的发送人为 发送人姓名<发送人邮件地址>,显示的内容为 发送的邮件内容...
包含命令执行结果的MAIL发送:
echo -e `ls /tmp`|mail -s "test" -r xx@xx.com fff@aaa.com < /tmp/dd.txt

i 忽略 tty 的中断讯号。(interrupt)
I 强迫设成互动模式。(Interactive)
v 列印出讯息,例如送信的地点、状态等等。(verbose)
n 不读入 mail.rc 设定档。
s 邮件标题。
c cc 抄送邮件地址。
b bcc密送邮件地址

需要sendmail或postfix服务

如果单纯的发文件文件可以用
cat xxxx.txt |mail -s "主旨" abc@xxx.com fff@xxx.com

如果需要发送附件需要安装uuencode来编码 (yum install sharutils)
单独发附件,这样xxxx@xxx.com会收到一个data.txt的附件
uuencode /tmp/data_process.log  data.txt |mail xxx@xxx.com

如果需要正文和附件一起发:
uuencode /tmp/data_process.log  data.txt > /tmp/data_temp.txt
 

系统收到邮件都会保存在“/var/spool/mail/[linux用户名]”文件中。在linux中输入mail ,就进行了收件箱,并显示二十封邮件列表。


利用外部的smpt服务器:
通过修改配置文件可以使用外部SMTP服务器,可以不安装sendmail或postfix:
修改/etc/nail.rc (/etc/mail.rc)
set from=fromUser@domain.com smtp=smtp.domain.comset smtp-auth-user=username smtp-auth-password=passwordset smtp-auth=login

说明:
from        是发送的邮件地址
smtp        是发生的外部smtp服务器的地址
smtp-auth-user            是外部smtp服务器认证的用户名
smtp-auth-password        是外部smtp服务器认证的用户密码
smtp-auth                是邮件认证的方式

测试:
mail -s "test" username@163.com < content.txt 其中-s后面的是邮件标题,user@sohu.com是收件人地址,content.txt里面是邮件正文

mail 命令的使用
mailq可以查看系统队列

 

sendmail 发送:

 

echo "From: sender <sender@domain.com>
To: to <to@domain.com>
Content-type: text/html;charset=utf-8
Subject: Saying Hello

内容1行
内容2行
内容3行
内容4行
" | sendmail to@domain.com

发表在 linux | 标签为 | linux mail已关闭评论

systemctl

systemd查看开机自启动的程序(相当于chkconfig --list)

ll /etc/systemd/system/multi-user.target.wants/

 

运行一个服务:

systemctl start network.service

关闭网络服务:

systemctl stop network.service

重启网络服务:

systemctl restart network.service

显示一个服务(无论运行与否)的状态:

systemctl status network.service

在开机时启用一个服务:

systemctl enable network.service

在开机时禁用一个服务:

systemctl disable network.service

查看服务开机是否启动:

systemctl is-enabled network.service

 

常用systemctl命令start,stop,restart,status,enable,disable,is-enabled,is-active。

 

####################

1. 列出所有可用单元

# systemctl list-unit-files

2. 列出所有运行中单元

# systemctl list-units

3. 列出所有失败单元

# systemctl –failed

4. 检查某个单元(如 crond.service)是否启用

# systemctl is-enabledcrond.service

5. 列出所有服务

# systemctl list-unit-files –type=service

6. Linux中如何启动、重启、停止、重载服务以及检查服务(如 httpd.service)状态

# systemctl start httpd.service

# systemctl restart httpd.service

# systemctl stop httpd.service

# systemctl reload httpd.service

# systemctl status httpd.service

注意:当我们使用systemctl的start,restart,stop和reload命令时,终端不会输出任何内容,只有status命令可以打印输出。

7. 如何激活服务并在开机时启用或禁用服务(即系统启动时自动启动mysql.service服务)

# systemctl is-active mysql.service

# systemctl enable mysql.service

# systemctl disable mysql.service

8. 如何屏蔽(让它不能启动)或显示服务(如ntpdate.service)

# systemctl mask ntpdate.service

ln -s ‘/dev/null”/etc/systemd/system/ntpdate.service’

# systemctl unmask ntpdate.service

rm ‘/etc/systemd/system/ntpdate.service’

9. 使用systemctl命令杀死服务

# systemctl killcrond

10. 列出所有系统挂载点

# systemctl list-unit-files –type=mount

11. 挂载、卸载、重新挂载、重载系统挂载点并检查系统中挂载点状态

# systemctl start tmp.mount

# systemctl stop tmp.mount

# systemctl restart tmp.mount

# systemctl reload tmp.mount

# systemctl status tmp.mount

12. 在启动时激活、启用或禁用挂载点(系统启动时自动挂载)

# systemctl is-active tmp.mount

# systemctl enable tmp.mount

# systemctl disable tmp.mount

13. 在Linux中屏蔽(让它不能启用)或可见挂载点

# systemctl mask tmp.mount

ln -s ‘/dev/null”/etc/systemd/system/tmp.mount’

# systemctl unmask tmp.mount

rm ‘/etc/systemd/system/tmp.mount’

14. 列出所有可用系统套接口

# systemctl list-unit-files –type=socket

15. 检查某个服务的所有配置细节

# systemctl showmysql

16. 获取某个服务(httpd)的依赖性列表

# systemctl list-dependencies httpd.service

17. 启动救援模式

# systemctl rescue

18. 进入紧急模式

# systemctl emergency

19. 列出当前使用的运行等级

# systemctl get-default

20. 启动运行等级5,即图形模式

# systemctl isolate runlevel5.target

# systemctl isolate graphical.target

21. 启动运行等级3,即多用户模式(命令行)

# systemctl isolate runlevel3.target

# systemctl isolate multiuser.target

22. 设置多用户模式或图形模式为默认运行等级

# systemctl set-default runlevel3.target

# systemctl set-default runlevel5.target

23. 重启、停止、挂起、休眠系统或使系统进入混合睡眠

# systemctl reboot

# systemctl halt

# systemctl suspend

# systemctl hibernate

# systemctl hybrid-sleep

对于不知运行等级为何物的人,说明如下。

Runlevel 0 : 关闭系统

Runlevel 1 : 救援,维护模式

Runlevel 3 : 多用户,无图形系统

Runlevel 4 : 多用户,无图形系统

Runlevel 5 : 多用户,图形化系统

Runlevel 6 : 关闭并重启机器

 

...

 

 

 

 

发表在 linux | systemctl已关闭评论

nc

测试80端口

nc -z -w 1 www.google.com  80

nmap -sT www.google.com -p  80

 

测试UDP 53端口

nc -u -z -w 1 8.8.8.8 53

nmap -sU 8.8.8.8 -p 53

 


发表在 linux | 标签为 | nc已关闭评论

Linux查看内存使用情况的方法

内容来源于网络

1. /proc/meminfo

查看RAM使用情况最简单的方法是通过/proc/meminfo。这个动态更新的虚拟文件实际上是许多其他内存相关工具(如:free / ps / top)等的组合显示。/proc/meminfo列出了所有你想了解的内存的使用情况。进程的内存使用信息也可以通过/proc/<pid>/statm 和 /proc/<pid>/status 来查看。

1

$ cat /proc/meminfo

点击查看原图

2. atop

atop命令是一个终端环境的监控命令。它显示的是各种系统资源(CPU, memory, network, I/O, kernel)的综合,并且在高负载的情况下进行了彩色标注。

1

$ sudo atop

点击查看原图

3. free

free命令是一个快速查看内存使用情况的方法,它是对 /proc/meminfo 收集到的信息的一个概述。

1

$ free -h

点击查看原图

4. GNOME System Monitor

GNOME System Monitor 是一个显示最近一段时间内的CPU、内存、交换区及网络的使用情况的视图工具。它还提供了一种查看CPU及内存使用情况的方法。

1

$ gnome-system-monitor

点击查看原图

5. htop

htop命令显示了每个进程的内存实时使用率。它提供了所有进程的常驻内存大小、程序总内存大小、共享库大小等的报告。列表可以水平及垂直滚动。

1

$ htop

点击查看原图

6. KDE System Monitor

功能同 4 中介绍的GENOME版本。

1

$ ksysguard

点击查看原图

7. memstat

memstat是一个有效识别executable(s), process(es) and shared libraries使用虚拟内存情况的命令。给定一个进程ID,memstat可以列出这个进程相关的可执行文件、数据和共享库。

1

$ memstat -p <PID>

点击查看原图

8. nmon

nmon是一个基于ncurses的系统基准测试工具,它可以监控CPU、内存、I/O、文件系统及网络资源等的互动模式。对于内存的使用,它可以实时的显示 总/剩余内存、交换空间等信息。

1

$ nmon

点击查看原图


9. ps

ps命令可以实时的显示各个进程的内存使用情况。Reported memory usage information includes
%MEM (percent of physical memory used), VSZ (total amount of virtual
memory used), and RSS (total amount of physical memory used)。你可以使用
“–sort”选项对进程进行排序,例如按RSS进行排序:

1

$ ps aux --sort -rss

点击查看原图

10. smem

smem命令允许你统计基于/proc信息的不同进程和用户的内存使用情况。内存使用情况的分析可以导出图表(如条形图和饼图)。

1

$ sudo smem --pie name -c "pss"

点击查看原图

11. top

top命令提供了实时的运行中的程序的资源使用统计。你可以根据内存的使用和大小来进行排序。

1

$ top

点击查看原图

12. vmstat

vmstat命令显示实时的和平均的统计,覆盖CPU、内存、I/O等内容。例如内存情况,不仅显示物理内存,也统计虚拟内存。

1

$ vmstat -s

发表在 linux | 标签为 , | Linux查看内存使用情况的方法已关闭评论

磁盘性能测试方法

测试随机写IOPS:

fio -direct=1 -iodepth=128 -rw=randwrite -ioengine=libaio -bs=4k
-size=10G -numjobs=1 -runtime=1000 -group_reporting
-name=/path/testfile

测试随机读IOPS:

fio -direct=1 -iodepth=128 -rw=randread -ioengine=libaio -bs=4k
-size=10G -numjobs=1 -runtime=1000 -group_reporting
-name=/path/testfile

测试写吞吐量:

fio -direct=1 -iodepth=64 -rw=randwrite -ioengine=libaio -bs=64k
-size=10G -numjobs=1 -runtime=1000 -group_reporting
-name=/path/testfile

测试读吞吐量:

fio -direct=1 -iodepth=64 -rw=randread -ioengine=libaio -bs=64k
-size=10G -numjobs=1 -runtime=1000 -group_reporting
-name=/path/testfile

 

案例:

写:time dd if=/dev/zero of=/mnt/mfs/test2/test500M bs=1024k count=500
读:time dd if=/mnt/mfs/test2/test500M of=/dev/null

1copy写     2copy写     1copy读     2copy读    
1M   0m0.042s 0m0.042s 0m0.017s 0m0.017s
5M 0m0.073s 0m0.079s 0m0.070s 0m0.071s
20M 0m0.250s 0m0.288s 0m0.291s 0m0.376s
50M 0m0.514s 0m0.589s 0m0.896s 0m0.886s
100M 0m0.977s 0m7.497s 0m1.677s 0m1.787s
200M   0m7.910s 0m22.270s 0m2.683s 0m3.129s
500M 0m22.465s 0m51.735s 0m6.559s 0m6.990s
1G 0m52.346s 1m48.056s 0m17.319s 0m17.154s
2G 1m46.224s 3m46.283s 0m41.608s 0m34.435s
10G 9m29.037s 19m26.237s 3m55.222s 3m24.914s

...

发表在 linux | 磁盘性能测试方法已关闭评论

.NET 资源回收

MSDN建议按照下面的模式实现IDisposable接口:

 public class Foo: IDisposable
{
    public void Dispose()
    {
       Dispose(true);
       GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
     {
        if (!m_disposed)
        {
            if (disposing)
            {
               // Release managed resources
            }
 
            // Release unmanaged resources
 
            m_disposed = true;
        }
     }
 
     ~Foo()
     {
        Dispose(false);
     }
 
     private bool m_disposed;
}

CSDN上一位高手的总结

1、Finalize方法(C#中是析构函数,以下称析构函数)是用于释放非托管资源的,而托管资源会由GC自动回收。所以,我们也可以这样来区分 托管和非托管资源。所有会由GC自动回收的资源,就是托管的资源,而不能由GC自动回收的资源,就是非托管资源。在我们的类中直接使用非托管资源的情况很 少,所以基本上不用我们写析构函数。

2、大部分的非托管资源会给系统带来很多负面影响,例如数据库连接不被释放就可能导致连接池中的可用数据库连接用尽。文件不关闭会导致其它进程无法读写这个文件等等。

实现模型:
1、由于大多数的非托管资源都要求可以手动释放,所以,我们应该专门为释放非托管资源公开一个方法。实现IDispose接口的Dispose方法是最好的模型,因为C#支持using语句快,可以在离开语句块时自动调用Dispose方法。

2、虽然可以手动释放非托管资源,我们仍然要在析构函数中释放非托管资源,这样才是安全的应用程序。否则如果因为程序员的疏忽忘记了手动释放非托管资源, 那么就会带来灾难性的后果。所以说在析构函数中释放非托管资源,是一种补救的措施,至少对于大多数类来说是如此。

3、由于析构函数的调用将导致GC对对象回收的效率降低,所以如果已经完成了析构函数该干的事情(例如释放非托管资源),就应当使用SuppressFinalize方法告诉GC不需要再执行某个对象的析构函数。

4、析构函数中只能释放非托管资源而不能对任何托管的对象/资源进行操作。因为你无法预测析构函数的运行时机,所以,当析构函数被执行的时候,也许你进行操作的托管资源已经被释放了。这样将导致严重的后果。

5、(这是一个规则)如果一个类拥有一个实现了IDispose接口类型的成员,并创建(注意是创建,而不是接收,必须是由类自己创建)它的实例对象,则 这个类也应该实现IDispose接口,并在Dispose方法中调用所有实现了IDispose接口的成员的Dispose方法。
只有这样的才能保证所有实现了IDispose接口的类的对象的Dispose方法能够被调用到,确保可以手动释放任何需要释放的资源。

进阶:

在.NET的对象中实际上有两个用于释放资源的函数:Dispose和Finalize。Finalize的目的是用于释放非托管的资源,而Dispose是用于释放所有资源,包括托管的和非托管的。

在这个模式中,void Dispose(bool disposing)函数通过一个disposing参数来区别当前是否是被Dispose()调用。如果是被Dispose()调用,那么需要同时释放 托管和非托管的资源。如果是被~Foo()(也就是C#的Finalize())调用了,那么只需要释放非托管的资源即可。

这是因为,Dispose()函数是被其它代码显式调用并要求释放资源的,而Finalize是被GC调用的。在GC调用的时候Foo所引用的其它 托管对象可能还不需要被销毁,并且即使要销毁,也会由GC来调用。因此在Finalize中只需要释放非托管资源即可。另外一方面,由于在 Dispose()中已经释放了托管和非托管的资源,因此在对象被GC回收时再次调用Finalize是没有必要的,所以在Dispose()中调用 GC.SuppressFinalize(this)避免重复调用Finalize。

然而,即使重复调用Finalize和Dispose也是不存在问题的,因为有变量m_disposed的存在,资源只会被释放一次,多余的调用会被忽略过去。

因此,上面的模式保证了:

1、 Finalize只释放非托管资源;

2、 Dispose释放托管和非托管资源;

3、 重复调用Finalize和Dispose是没有问题的;

4、 Finalize和Dispose共享相同的资源释放策略,因此他们之间也是没有冲突的。

在C#中,这个模式需要显式地实现,其中C#的~Foo()函数代表了Finalize()。而在C++/CLI中,这个模式是自动实现的,C++的类析构函数则是不一样的。

按照C++语义,析构函数在超出作用域,或者delete的时候被调用。在Managed C++(即.NET 1.1中的托管C++)中,析构函数相当于CLR中的Finalize()方法,在垃圾收集的时候由GC调用,因此,调用的时机是不明确的。在.NET 2.0的C++/CLI中,析构函数的语义被修改为等价与Dispose()方法,这就隐含了两件事情:

1、 所有的C++/CLI中的CLR类都实现了接口IDisposable,因此在C#中可以用using关键字来访问这个类的实例。

2、 析构函数不再等价于Finalize()了。

对于第一点,这是一件好事,我认为在语义上Dispose()更加接近于C++析构函数。对于第二点,Microsoft进行了一次扩展,做法是引入了“!”函数,如下所示:

public ref class Foo
{
    public:
    Foo();
    ~Foo(); // destructor
    !Foo(); // finalizer
};

“!”函数(我实在不知道应该怎么称呼它)取代原来Managed C++中的Finalize()被GC调用。MSDN建议,为了减少代码的重复,可以写这样的代码:

~Foo()
{
    //释放托管的资源
    this->!Foo();
}

!Foo()
{
//释放非托管的资源
}

对于上面这个类,实际上C++/CLI生成对应的C#代码是这样的:

 

 public class Foo
{

    private void !Foo()

    {
    // 释放非托管的资源
    }

    private void ~Foo()
    {
         // 释放托管的资源
         !Foo();
     }
    
     public Foo()
     {
     }
    
     public void Dispose()
     {
         Dispose(true);
         GC.SuppressFinalize(this);
     }
    
     protected virtual void Dispose(bool disposing)
     {
         if (disposing)
         {
            ~Foo();
         }
         else
         {
             try
             {
                !Foo();
             }
             finally
             {
                base.Finalize();
             }
         }
     }
    
     protected void Finalize()
     {
        Dispose(false);
     }
}

 

 

由于~Foo()和!Foo()不会被重复调用(至少MS这样认为),因此在这段代码中没有和前面m_disposed相同的变量,但是基本的结构是一样的。


并且,可以看到实际上并不是~Foo()和!Foo()就是Dispose和Finalize,而是C++/CLI编译器生成了两个Dispose 和Finalize函数,并在合适的时候调用它们。C++/CLI其实已经做了很多工作,但是唯一的一个问题就是依赖于用户在~Foo()中调 用!Foo()。

 

他人写的一段小程序(仅拷贝,未验证)

 测试:

 

    public class b : IDisposable
    {
        public int i;
        public b() { Console.WriteLine("ctor"); }
        ~b() { Console.WriteLine("dtor"); }
        public void Dispose()
        {
            Console.WriteLine("Dispose");
            GC.SuppressFinalize(true);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            b objb = new b { i = 2 };
            using (objb)
            {
                Console.WriteLine("using");
            }
            Console.WriteLine("after using");
        }
    }

  输出:

 

ctor
using
Dispose
after using
dtor
Press any key to continue . . .

 

发表在 .net | 标签为 | .NET 资源回收已关闭评论

HttpUtility.UrlEncode

 using System;
using System.IO;

namespace NETCFDevelopersReference
{
    
/// <summary>
    
/// Replacement for HttpUtility.UrlEncode
    
/// </summary>
    public class HttpUtility
    {
        
public static string UrlEncode(string instring)
        {
            StringReader strRdr 
= new StringReader(instring);
            StringWriter strWtr 
= new StringWriter();
            
int charValue = strRdr.Read();
            
while (charValue != -1)
            {
                
if (((charValue >= 48&& (charValue <= 57)) // 0-9
                    ││((charValue >= 65&& (charValue <= 90)) // A-Z
                    ││((charValue >= 97&& (charValue <= 122))) // a-z
                    strWtr.Write((char) charValue);
                
else if (charValue == 32)    // Space
                    strWtr.Write('+');
                
else 
                    strWtr.Write(
"%{0:x2}", charValue);

                charValue = strRdr.Read();
            }

            return strWtr.ToString();
        }
    }
}


发表在 .net | HttpUtility.UrlEncode已关闭评论

emoji

点击查看原图

一 参考资料

1 Emoji 全编码表:(我参考的这个)
  http://punchdrunker.github.com/iOSEmoji/table_html/flower.html
2 Emoji全编码表
  http://code.iamcal.com/php/emoji/
http://blog.csdn.net/iunion/article/details/7241945

3 iOS5/4 Emoji  兼容性:
  http://stackoverflow.com/questions/7856775/how-to-convert-the-old-emoji-encoding-to-the-latest-encoding-in-ios5
4 MySQL emoji问题
  http://dropblood.com/archives/ios-mysql-emoji
5 Emoji 中文对应表

  http://www.iapps.im/wp-content/uploads/2012/02/emoji-pinyin.png?r=010
6 Emoji 参考
   http://www.unicode.org/emoji/
   对照:
        http://www.unicode.org/Public/emoji/2.0//emoji-data.txt
        http://www.unicode.org/Public/emoji/2.0//emoji-sequences.txt
        http://www.unicode.org/Public/emoji/2.0//emoji-zwj-sequences.txt
7 Emoji UTF-16
        http://punchdrunker.github.io/iOSEmoji/table_html/emoji.json
8 windows 7 补丁

        https://support.microsoft.com/zh-cn/kb/2729094

 9 php
http://ju.outofmemory.cn/entry/46760

http://www.unicode.org/~scherer/emoji4unicode/snapshot/full.html

二 下载资源 

emoji图片和编码表 http://download.csdn.net/detail/qdkfriend/4309051

  包括emoji文件表,emoji数据编码表(Unicode编码,UTF8编码,UTF16编码,SBUnicode编码)

public static function removeEmoji($text) {

    $clean_text = "";

    // Match Emoticons
    $regexEmoticons = '/[\x{1F600}-\x{1F64F}]/u';
    $clean_text = preg_replace($regexEmoticons, '', $text);

    // Match Miscellaneous Symbols and Pictographs
    $regexSymbols = '/[\x{1F300}-\x{1F5FF}]/u';
    $clean_text = preg_replace($regexSymbols, '', $clean_text);

    // Match Transport And Map Symbols
    $regexTransport = '/[\x{1F680}-\x{1F6FF}]/u';
    $clean_text = preg_replace($regexTransport, '', $clean_text);

    // Match Miscellaneous Symbols
    $regexMisc = '/[\x{2600}-\x{26FF}]/u';
    $clean_text = preg_replace($regexMisc, '', $clean_text);

    // Match Dingbats
    $regexDingbats = '/[\x{2700}-\x{27BF}]/u';
    $clean_text = preg_replace($regexDingbats, '', $clean_text);

    return $clean_text;
}

 

static string EmojiToHex(string content)
        {
            if (string.IsNullOrEmpty(content))
            {
                return content;
            }

            //http://punchdrunker.github.io/iOSEmoji/table_html/emoji.json
            var regexString = @"\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDEFF]";
            var regex = new System.Text.RegularExpressions.Regex(regexString);
            var contentHex = regex.Replace(content, m =>
            {
                int r;
                string r1, r2;

                r = Convert.ToInt32(m.Value[0]);
                r1 = "0x" + r.ToString("X");

                r = Convert.ToInt32(m.Value[1]);
                r2 = "0x" + r.ToString("X");

                return r1 + r2;
            });

            return contentHex;
        }
        
        static string EmojiFromHex(string hexContent)
        {
            if (string.IsNullOrEmpty(hexContent))
            {
                return hexContent;
            }
            var regexString = @"0x[0-9A-Z]{4}|0x[0-9A-Z]{2}";
            var regex = new System.Text.RegularExpressions.Regex(regexString);
            var content = regex.Replace(hexContent, m =>
            {
                var b = m.Value.Substring(2);
                var b1 = Convert.ToInt32(b, 16);
                var b2 = Convert.ToChar(b1);
                return b2.ToString();
            });

            return content;
        }


 //test
            var c = "";
            c = System.Web.HttpUtility.UrlDecode("%ud83d%ude00中文", Encoding.UTF8);//
            Console.WriteLine(c);


            //var c1 = c.ToCharArray();

            var c1 = EmojiToHex(c);
            Console.WriteLine(c1);

            var c2 = EmojiFromHex(c1);
            Console.WriteLine(c2);

            return;

发表在 technologys | 标签为 | emoji已关闭评论

APNS

1、实现provider向APNS推送消息

在通过provider向APNS发送消息之前,我们首先需要了解需要发送的格式,APNS的信息结构包如下图:
点击查看原图

上图显示的这个消息体就是我们的服务器(Provider)发送给APNS服务器的消息结构,APNS验证这个结构正确并提取其中的信息后,再将消息推送到指定的设备。这个结构体包括七个部分:

第一个部分是命令标示符;

第二部分是一个表示这个通知的一个表示位,如果apns不能解释该通知,就返回一个错误包;

第三部分是一个以秒标识的时间值,它标识通知是否有效,标识的通知时间与UNIX之差与当前时间与UNIX时间之差,如果大于零,APNS最少通知一次,如果小于同于零APNS不在存储通知(网络字节顺序)。

第四个部分是我们的device_token的长度,

第五部分是我们的device_token字符串,

第六部分是推送消息体(Payload)的长度,

最后一部分也就是真正的消息内容了,里面包含了推送消息的基本信息,比如消息内容,应用Icon右上角显示多少数字以及推送消息到达时所播放的声音等。

接下来我们拆解看一下Payload(消息体)的结构:

点击查看原图

这其实就是个JSON结构体,alert标签的内容就是会显示在用户手机上的推送信息,badge显示的数量(注意是整型)是会在应用Icon右上角显示的数量,提示有多少条未读消息等,sound就是当推送信息送达是手机播放的声音,传defalut就标明使用系统默认声音,如果传比如“beep.wav”就会播放在我们应用工程目录下名称为beep.wav的音频文件,比如当手机锁屏时QQ在后台收到新消息时的滴滴声。

provider通过APNS提供的接口,通过Socket进行异步通信,

在Production环境下面通过gateway.push.apple.com,端口:2195

在Development环境下通过gateway.sandbox.push.apple.com 端口:2195

Provider可以建立多个与APNs的连接。每个都得用TLS(or SSL)来建立安全通道,需要用到SSL证书(就是上面提到的provider连接APNs要用到的SSL证书)。

发送消息的二进制接口和消息的数据包格式

消息须是网络字节顺序(即大尾顺序),消息里面的payload部分不可以超过256字节,且不得以'\0'结尾。

有这么一种情况,当我们将应用从设备卸载后,推送的消息改如何处理呢。我们知道,当我们将应用从设备卸载后,我们是收不到Provider给我们推送的消息的,但是,如何让APNS和Provider都知道不去向这台卸载了应用的设备推送消息呢?针对这个问题,苹果也已经帮我们解决了,那就是Feedback
service。他是APNS的一部分,APNS会持续的更新Feedback service的列表,当我们的Provider将信息发给APNS推送到我们的设备时,如果这时设备无法将消息推送到指定的应用,就会向APNS服务器报告一个反馈信息,而这个信息就记录在feedback service中。按照这种方式,Provider应该定时的去检测Feedback service的列表,然后删除在自己数据库中记录的存在于反馈列表中的device_token,从而不再向这些设备发送推送信息。连接Feedback service的过程同样使用Socket的方式,连接上后,直接接收由APNS传输给我们的反馈列表,传输完成后断开连接,然后我们根据这个最新的反馈列表在更新我们自己的数据库,删除那些不再需要推送信息的设备的device_token。从Feedback
service读取的数据结构如下:
点击查看原图

结构中包含三个部分,第一部分是一个时间戳,记录的是设备失效后的时间信息,第二个部分是device_token的长度,第三部分就是失效的device_token,我们所要获取的就是第三部分,跟我们的数据库进行对比后,删除对应的device_token,下次不再向这些设备发送推送信息。

The Feedback Service

feedback service包含了这样的列表:某iOS应用程序对应的"设备"("设备"用二进制格式的设备token来标识)。--这些设备是由于各种原因而不能接收APNs发来的消息。

Provider应该定期查询这个列表,并且作出对应处理,如:停止向这些的设备发送消息。

provider访问feedback server通过一个与发送消息类似的二进制接口。

Production环境通过feedback.push.apple.com:2196来建立连接,Development通过feedback.sandbox.push.apple.com:2196。

feedback service和发送消息是不同的服务接口(但都属于APNs),他的连接方式和发送消息是一样的。也要通过证书建立SSL连接,连接后你不需要发送任何命令,直接开始读取流一直读完为止,然后provider要解析读到的数据。

数据是由多个这样的格式组成的:

| 四字节时间 | 2字节的token 长度 | 32字节的设备token |

关 于"四字节时间":Provider需要判断对应设备的这个iOS应用程序有没有在该时间之后重新像provider发送注册推送消息所获得的设备 token。如果没有,就认为该设备失效了,需停止向该设备发送消息。如果有,那就是这个设备失效过,但是现在又有效了,只是feedback service还没来得及刷新列表。

 

简单通知报文

点击查看原图

 

最前面1个字节是命令类型,2-3字节是DeviceToken的长度,后面是DeviceToken的具体值,后面是消息的长度和消息的具体内容。发完消息后,在关闭Socket前还可以查看错误的响应,以便确认消息是否成功地发给APNS,错误响应的报文如下:

点击查看原图

命令为8的表示是错误响应的报文,Status是错误码,Identifier是用于定位具体的哪条推送消息,这个是增强型通知里的传入的值,首先看下苹果都有哪些返回错误码:

点击查看原图

 

增强型通知报文(传入Identifier):

点击查看原图

 

Figure 5-1  Notification format

The first byte in the notification format is a command value of 1. The remaining fields are as follows:

    Identifier—An arbitrary value that identifies this notification. This same identifier is returned in a error-response packet if APNs cannot interpret a notification.

    Expiry—A fixed UNIX epoch date expressed in seconds (UTC) that identifies when the notification is no longer valid and can be discarded. The expiry value uses network byte order (big endian). If the expiry value is positive, APNs tries to deliver the notification at least once. Specify zero (or a value less than zero) to request that APNs not store the notification at all.

    Token length—The length of the device token in network order (that is, big endian)

    Device token—The device token in binary form.

    Payload length—The length of the payload in network order (that is, big endian). The payload must not exceed 256 bytes and must not be null-terminated.

 

批量发送

应使用长连接,一次连接发送多条数据

以下部份内容摘自: http://blog.csdn.net/tlq1988/article/details/9612237

 $pass = ''; // $pass是你在建立证书的时候输入的密码
$ctx = stream_context_create();
// apns.pem就是你的证书的路径了,最好写绝对路径
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apns.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if(!$fp) {
    print "Failed to connect $err $errstr";
    exit();
} else {
    print "Connection OK\n";
}
$body = array('aps' => array('badge' => 1));
for($i = 0; $i <= 10000; $i++) {
    $deviceToken = md5(time() . rand(0, 9999999)) . md5(time() . rand(0, 9999999)); // 模拟一个Device Token
    $body['aps']['alert'] = md5(time() . rand(0, 9999999)); // 随便模拟点数据
    $payload = json_encode($body);
    // 这里是简单的消息结构,如果想多发几个但是不要返回错误,可以用这个
    /*
    $msg = chr(0) . pack("n", 32)
        . pack('H*', str_replace(' ', '', $deviceToken))
        . pack("n", strlen($payload)) . $payload;
    */
    // 这个是增强型消息格式,$i就是Identifier,864000就是Expiry了
    $msg = pack('CNNnH*', self::COMMAND_PUSH, $i, 864000, 32, $deviceToken)
        . pack('n', strlen($payload))
        . $payload;
    print "sending message :" . $payload . "\n";
    fwrite($fp, $msg);
    // 这里是读取错误信息,不要没发一条就读取一次,这样苹果会认为攻击而终止连接
    //fread($fp, 6);
}

Broken Pipe,如果你有过大量的数据推送,并且看下你的错误日志那么Writen Broken Pipe你一定不陌生。这个错误产生的原因通常是当管道读端没有在读,而管道的写端继续有线程在写,就会造成管道中断。可以简单的理解为你在向一个已经关闭的连接写数据就会抛出这个错误。

    由于Broken
Pipe的关系,我们不得不重新和苹果服务器建立连接,这个连接耗时在国内.....(你们懂的3sec+),这个应该是我们推送速度最大的瓶颈了。有很
多开发者也许会认为这个是由于国内的网络环境导致,因为他们习惯的“traceroute
gateway.push.apple.com”一下,然后发现30+的路由跳转然后就会说这个断开是无法避免的。如果你这么想那么你就错了

    我们用大量(10W左右)能保证基本正确的Device Token来做测试,平均一次连接的能写入3W左右的数据,好的情况下能一次写完这10W数据!!!这个测试也就证明平凡出现Broken Pipe不是由于网络原因。既然不是由于网络原因,那么我做个大胆的假设:这个连接是由APNs主动断开的

   
那么假设这个猜想是正确的,那苹果什么时候会断开连接了?解释这个问题,我们又做了一个测试:往这10W的Device
Token里面均匀插入1000个错误的Device
Token。神奇的事情发生了,发送期间平均断开连接900次+。这个实验正好验证了我之前的猜测:产生Broken Pipe是因为APNs服务器主动断开了连接,并且是由于错误的Device Token引起的(或者其他的错误)。苹果的错误类型和代码编号:

Status code

Description

0

No errors encountered

1

Processing error

2

Missing device token

3

Missing topic

4

Missing payload

5

Invalid token size

6

Invalid topic size

7

Invalid payload size

8

Invalid token

10

Shutdown

255

None (unknown)

    我们进一步跟进测试,我们发现一个奇怪的现象,断开连接的时的前一个Token并不是我们所特意设置的错误Token。同时我们也发现消息送达率也变得非常的低(偶尔有设备能收到)。这个很好解释,之前我就有文章提到过(官方也有相应说明)当一次连接先发送一个错误的Token,之后的有效Token的消息是无法送达的(http://blog.csdn.net/hjq_tlq/article/details/8131115),这就导致了错误的Token后面的正确的Token全部没有收到,从而送达率也就明显下降了。

    经过上面的测试,当APNs接收到错误的Token的时候会主动断开连接,但是断开连接之前会有1sec左右的延迟。那么你可以有下面这个例子理解:

        你要发送1000条数据并且第20个Token是错误的

        当此次连接发到第20个Token的时候苹果认为此次连接终止(但是连接并没有断开,只是APNs将抛弃之后的内容),并且不处理此次连接之后的消息

        1sec左右的时间之后苹果主动断开SSL连接,如果你继续忘此连接写数据,你将可以捕捉到Broken Pipe错误

        此时由于1sec左右的延迟,你已经发送到了第123个消息

        此时从20以后直至123的消息将全部没有送达

    太可怕了.....你竟然不知道是从哪一个错了!!!苹果是SB啊!先不要做这样的结论,我们先看一下苹果官方文档所给出的东东:

点击查看原图

  • Identifier—An arbitrary value that identifies this notification. This same identifier is returned in a error-response packet
    if APNs cannot interpret a notification.

  • Expiry—A
    fixed UNIX epoch date expressed in seconds (UTC) that identifies when
    the notification is no longer valid and can be discarded. The expiry
    value
    uses network byte order (big endian). If the expiry value is positive,
    APNs tries to deliver the notification at least once. Specify zero (or a
    value less than zero) to request that APNs not store the notification
    at all.

  • Token length—The length of the device token in network order (that is, big endian)

  • Device token—The device token in binary form.

  • Payload length—The length of the payload in network order (that is, big endian). The payload must not exceed 256 bytes and must not be null-terminated.

  • Payload—The notification payload.

   
PS:这里苹果到是做了件好事,这个消息结构在早些的文档中显示的是5-2 Enhanced Notification
Format,而之前的5-1是Notification
Format。区别在于之前的5-1中的消息结构为简单消息结构,没有Identifier和Expiry字段并且Command为0。现在直接把简单的
消息体结构给去掉了,这样可以强制开发者加上Identifier,从而得到返回值。

   
为了方便我直接把官方文档粘过来了哈:)我们需要注意的是Identifier这个东东。没错,这个就是苹果用来提供的给第三方的4唯一标示,如果鸟语不
是很好的话他后面的那个注释大致就是说:一个消息的唯一标识。如果苹果服务器不能解释这个消息,那么将在错误中返回这个唯一标示。

    可恶的苹果并没有说明这个会有延迟,以及怎么确保我们能收到这个错误。我们现在采用的是每发送100条消息,就检查一下(read)是否有失败的。如果你抓到这个错误,那么果断断开连接,并且重新发送这条错误以后的Token,这样就能保证消息基本能送达。

    哦,顺便说一下如何得到错误反馈,如果你发送的时候加上了Identifier,那么此时你一定有一个和APNs的连接吧(废话,没连接怎么write),那么你只要read就好了,如果有就能读到一个二进制数据:)

    有一个也需要提一下,就是APNs的FeedBack功能也一定要用上,这个能帮助你更好的剔除错误的Token。

    当你的Token基本为正确的时候,如果还有大量的Broken Pipe出现,你可以给我留言,我们一起研究到底哪里出问题了:)

 

附: http://www.oschina.net/translate/http2-protocol-for-apns?cmp

 
其它:

2015年12月17日起,发布 “基于 HTTP/2 的全新 APNs 协议”,iOS 系统以及 OS X 系统,统一将最大
playload 大小提升到4KB。参考文档:Apple Push Notification Service Update 12-17 2015

  新旧 APNs 协议工作示意图对比

点击查看原图

    HTTP / 2
 点击查看原图
  
Version Old / socket connect
 
点击查看原图
参考:
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW2

APNS架构图:

点击查看原图

发表在 technologys | APNS已关闭评论

BAT 路径

例子:
@echo off
echo 当前盘符:%~d0
echo 当前盘符和路径:%~dp0
echo 当前盘符和路径的短文件名格式:%~sdp0
echo 当前批处理全路径:%~f0
echo 当前CMD默认目录:%cd%

pause

 

通过批处理取当前目录的上一级目录
@echo off
if %cd%==%cd:~,3% echo 当前目录已经是%cd:~,1%盘的根目录!&goto end
cd..
set "bd=%cd%"
cd..
set "bbd=%cd%"
if "%bbd%"=="%bd%" (echo 上一级目录是: %cd:~,1%盘的根目录!
) else call echo 上一级目录是: "%%bd:%bbd%\=%%"
:end
pause

发表在 windows | 标签为 | BAT 路径已关闭评论

顶级域名注册局列表(Registry Listing)

顶级域名 开始推行 是否赞助 用途 赞助商或运营商 网址
.aero 2001 赞助 航空业
Air-transport industry
Societe Internationale de Telecommunications Aeronautiques SC, (SITA) www.information.aero
.asia 2007 赞助 亚洲地区
From Asia/For Asia
DotAsia Organisation www.registry.asia
.biz 2001 非赞助 商务Businesses NeuLevel www.nic.biz
.cat 2005 赞助 加泰罗尼亚语/文化使用
Catalan linguistic & cultural community
Fundació puntCAT www.domini.cat
.com 1995 非赞助 不限(但开始是针对商业注册人,是commercial的宿写)

Unrestricted (but intended for commercial registrants)

VeriSign, Inc. www.verisign-grs.com
.coop 2001 赞助 合伙机构
Cooperatives
DotCooperation, LLC www.communicate.coop
.edu 1995 赞助 美国教育机构
United States educational institutions
EDUCAUSE www.educause.edu/edudomain
.gov 1995 赞助 美国政府机构
United States government
US General Services Administration www.nic.gov
.info 2001 非赞助 不限
Unrestricted use
Afilias Limited www.afilias.info
.int 1998 非赞助 政府间按照国际条约指定的组织
Organizations established by international treaties between governments
Internet Assigned Numbers Authority www.iana.org/int-dom/int.htm
.jobs 2005 赞助 人力资源管理的国际机构
International community of human resource managers
Employ Media LLC www.employmedia.com
.mil 1995 赞助 美国军队
United States military
US DoD Network Information Center www.nic.mil

.mobi 2005 赞助 移动服务商及用户社区
Mobile content providers and users community
mTLD Top Level Domain, LTD. www.mtld.mobi
.museum 2001 赞助 博物馆
Museums
Museum Domain Management Association, (MuseDoma) www.nic.museum
.name 2001 非赞助 个人
For registration by individuals
Global Name Registry, LTD www.gnr.name
.net 1995 非赞助 不限(但开始针对网络机构 network
Unrestricted (but intended for network providers, etc.)
VeriSign, Inc. www.verisign-grs.com
.org 1995 非赞助 不限(但开始针对非盈利的组织organization
Unrestricted (but intended for organizations that do not fit elsewhere)
Public Interest Registry. Until 31 December 2002, .org was operated by VeriSign Global Registry Services. www.pir.org
.pro 2002 非赞助 会计师、律师、医师等专业人士
Accountants, lawyers, physicians, and other professionals
RegistryPro, LTD www.registrypro.pro
.tel 2006 赞助 无说明 Telnic Ltd. www.telnic.org
.travel 2005 赞助 旅游           
Travel and tourism community
Tralliance Corporation www.tralliance.travel

 

 

发表在 network | 顶级域名注册局列表(Registry Listing)已关闭评论

msmq,rabbitmq,activemq,zeromq

摘自网络

RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统。

一些概念:

channel:通道,amqp支持一个tcp连接上启用多个mq通信通道,每个通道都可以被作为通信流。

producer:生产者,是消息产生的源头。

exchange:交换机,可以理解为具有路由表的路由规则。

queues:队列,装载消息的缓存容器。

consumer:消费者,连接到队列并取走消息的客户端。

核心思想:在RabbitMQ中,生产者从不直接将消息发送给队列。

事实上,有些生产者甚至不知道消息是否被送到某个队列中去了。生产者只负责将消息送给交换机,而交换机确切地知道什么消息应该送到哪。

bind:绑定,实际上可以理解为交换机的路由规则。每个消息都有一个称为路由键的属性(routing key),就是一个简单的字符串。一个绑定将【交换机,路由键,消息送达队列】三者绑定在一起,形成一条路由规则。

exchange type:交换机类型:

fanout:不处理路由键,转发到所有绑定的队列上

direct:处理路由键,必须完全匹配,即路由键字符串相同才会转发

topic:路由键模式匹配,此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs”

网络获取得一些综合的测试结果:

点击查看原图

 

 rabbitmq原型图

点击查看原图

 

 

 

 

发表在 db | 标签为 , , , | msmq,rabbitmq,activemq,zeromq已关闭评论

private ip range

私有IP就是在本地局域网上的IP 与之对应的是公有IP(在互联网上的IP)。
1、私有地址(Private address,也可称为专网地址)属于非注册地址,专门为组织机构内部使用,它是局域网范畴内的,私有IP禁止出现在Internet中,在ISP连接用户的地方,将来自于私有IP的流量全部都会阻止并丢掉。
2、随着私有IP网络的发展,为节省可分配的注册IP地址,有一组IP地址被拿出来专门用于私有IP网络,称为私有IP地址。
3、私有IP地址范围:
A: 10.0.0.0~10.255.255.255 即10.0.0.0/8
B:172.16.0.0~172.31.255.255即172.16.0.0/12
C:192.168.0.0~192.168.255.255 即192.168.0.0/16
4、
这些地址是不会被Internet分配的,它们在Internet上也不会被路由,虽然它们不能直接和Internet网连接,但通过技术手段仍旧可以和

Internet通讯(NAT技术)。可以根据需要来选择适当的地址类,在内部局域网中将这些地址像公用IP地址一样地使用。在Internet上,有些
不需要与 Internet通讯的设备,如打印机、可管理集线器等也可以使用这些地址,以节省IP地址资源。

发表在 network | 标签为 | private ip range已关闭评论

load average

CPU利用率与Load Average的区别?

CPU利用率,是对一个时间段内CPU使用状况的统计,通过这个指标可以看出在某一个时间段内CPU被占用的情况,如果CPU被占用时间很高,那么就需要考虑CPU是否已经处于超负荷运作,长期超负荷运作对于机器本身来说是一种损害,因此必须将CPU的利用率控制在一定的比例下,以保证机器的正常运作。

Load Average CPULoad,它所包含的信息不是CPU的使用率状况,而是在一段时间内CPU正在处理以及等待CPU处理的进程数之和的统计信息,也就是CPU使用队列的长度的统计信息。

那么CPU利用率与Load Average对于性能测试的意义有什么区别呢?实际上,CPU利用率反映的是CPU被使用的情况,当CPU长期处于被使用而没有得到足够的时间休息间歇,那么对于CPU硬件来说是一种超负荷的运作,需要调整使用频度。而Load Average却从另一个角度来展现对于CPU使用状态的描述,Load Average越高说明对于CPU资源的竞争越激烈,CPU资源比较短缺。对于资源的申请和维护其实也是需要很大的成本,所以在这种高Average Load的情况下CPU资源的长期“热竞争”也是对于硬件的一种损害。

如何评估性能需求中合理的Load Average

一般来说,Load Average是与机器内核数有关的。以一个单核的机器为例,load=0.5表示CPU还有一半的资源可以处理其他的线程请求,load=1表示CPU所有的资源都在处理请求,没有剩余的资源可以利用了,而load=2则表示CPU已经超负荷运作,另外还有一倍的线程正在等待处理。所以,对于单核机器来说,理想状态下,Load Average要小于1。同理,对于双核处理器来说,Load Average要小于2。结论是:多核处理器中,你的Load Average不应该高于处理器核心的总数量。

不同核处理器之间的load值怎样换算?

性能测试中可能遇到这样的问题,你的线上机器是8核的,但是线下性能测试机只有4核的与16核的,那么我用16核机器测试得到的load值是2.6,换算到8核机器上应该是多少呢?

很不幸,没有一个准确的公式可以用来换算。但是我们可以根据load的含义来做一个推断,假如我们在一个双核的机器上测试100个线程并发访问X页面时load2,那么同样的并发线程数请求同样的页面,在一台单核的机器上测试,load会是多少呢?在双核机器上,100线程同时请求时load2,说明2个核都在满负荷运作,且平均每一个核在同时处理50个线程;如果在单核机器上100个线程同时请求,并且假设每一个核还是能同时处理50个线程,那么就会有50个线程在等待,这样看起来CPUload还是2,但事实上,100个线程同时请求CPU时,已经超出了一个CPU可以同时处理的线程的能力,必然会出现线程之间竞争CPU资源的情况,而线程对CPU的“热竞争”会使CPU耗费更多的资源去做线程调度的事情,所以总体效果来看,单核时load值实际会高于2

上面是我自己的推论,网上还没有找到相应的资料验证。假如这种推论是对的,那么16核机器上测试得到的load2.6,在8核机器上测试的话load值肯定高于2.6究竟高多少应该跟CPU本身的性能也是有关的,具体我还不清楚该如何评估。有兴趣的同学可以一起来讨论讨论哦!

--------------------------------------------------------------------------------------

 

1、先使用top看下CPU占用高的进程,找出进程的进程ID(pid);

查看方法:top
2、根据进程ID(pid)查看是进程的那些线程占用CPU高。
查看方法:top -Hp pid
3、使用pstack,查看CPU占用高的线程在干什么。
查看方法:pstack pid
4、根据pstack分析,应该可以看出问题所在

发表在 linux | load average已关闭评论

php timezone

$timezones =
array (
 '(GMT-12:00) International Date Line West' => 'Pacific/Wake',
 '(GMT-11:00) Midway Island' => 'Pacific/Apia',
 '(GMT-11:00) Samoa' => 'Pacific/Apia',
 '(GMT-10:00) Hawaii' => 'Pacific/Honolulu',
 '(GMT-09:00) Alaska' => 'America/Anchorage',
 '(GMT-08:00) Pacific Time (US & Canada); Tijuana' => 'America/Los_Angeles',
 '(GMT-07:00) Arizona' => 'America/Phoenix',
 '(GMT-07:00) Chihuahua' => 'America/Chihuahua',
 '(GMT-07:00) La Paz' => 'America/Chihuahua',
 '(GMT-07:00) Mazatlan' => 'America/Chihuahua',
 '(GMT-07:00) Mountain Time (US & Canada)' => 'America/Denver',
 '(GMT-06:00) Central America' => 'America/Managua',
 '(GMT-06:00) Central Time (US & Canada)' => 'America/Chicago',
 '(GMT-06:00) Guadalajara' => 'America/Mexico_City',
 '(GMT-06:00) Mexico City' => 'America/Mexico_City',
 '(GMT-06:00) Monterrey' => 'America/Mexico_City',
 '(GMT-06:00) Saskatchewan' => 'America/Regina',
 '(GMT-05:00) Bogota' => 'America/Bogota',
 '(GMT-05:00) Eastern Time (US & Canada)' => 'America/New_York',
 '(GMT-05:00) Indiana (East)' => 'America/Indiana/Indianapolis',
 '(GMT-05:00) Lima' => 'America/Bogota',
 '(GMT-05:00) Quito' => 'America/Bogota',
 '(GMT-04:00) Atlantic Time (Canada)' => 'America/Halifax',
 '(GMT-04:00) Caracas' => 'America/Caracas',
 '(GMT-04:00) La Paz' => 'America/Caracas',
 '(GMT-04:00) Santiago' => 'America/Santiago',
 '(GMT-03:30) Newfoundland' => 'America/St_Johns',
 '(GMT-03:00) Brasilia' => 'America/Sao_Paulo',
 '(GMT-03:00) Buenos Aires' => 'America/Argentina/Buenos_Aires',
 '(GMT-03:00) Georgetown' => 'America/Argentina/Buenos_Aires',
 '(GMT-03:00) Greenland' => 'America/Godthab',
 '(GMT-02:00) Mid-Atlantic' => 'America/Noronha',
 '(GMT-01:00) Azores' => 'Atlantic/Azores',
 '(GMT-01:00) Cape Verde Is.' => 'Atlantic/Cape_Verde',
 '(GMT) Casablanca' => 'Africa/Casablanca',
 '(GMT) Edinburgh' => 'Europe/London',
 '(GMT) Greenwich Mean Time : Dublin' => 'Europe/London',
 '(GMT) Lisbon' => 'Europe/London',
 '(GMT) London' => 'Europe/London',
 '(GMT) Monrovia' => 'Africa/Casablanca',
 '(GMT+01:00) Amsterdam' => 'Europe/Berlin',
 '(GMT+01:00) Belgrade' => 'Europe/Belgrade',
 '(GMT+01:00) Berlin' => 'Europe/Berlin',
 '(GMT+01:00) Bern' => 'Europe/Berlin',
 '(GMT+01:00) Bratislava' => 'Europe/Belgrade',
 '(GMT+01:00) Brussels' => 'Europe/Paris',
 '(GMT+01:00) Budapest' => 'Europe/Belgrade',
 '(GMT+01:00) Copenhagen' => 'Europe/Paris',
 '(GMT+01:00) Ljubljana' => 'Europe/Belgrade',
 '(GMT+01:00) Madrid' => 'Europe/Paris',
 '(GMT+01:00) Paris' => 'Europe/Paris',
 '(GMT+01:00) Prague' => 'Europe/Belgrade',
 '(GMT+01:00) Rome' => 'Europe/Berlin',
 '(GMT+01:00) Sarajevo' => 'Europe/Sarajevo',
 '(GMT+01:00) Skopje' => 'Europe/Sarajevo',
 '(GMT+01:00) Stockholm' => 'Europe/Berlin',
 '(GMT+01:00) Vienna' => 'Europe/Berlin',
 '(GMT+01:00) Warsaw' => 'Europe/Sarajevo',
 '(GMT+01:00) West Central Africa' => 'Africa/Lagos',
 '(GMT+01:00) Zagreb' => 'Europe/Sarajevo',
 '(GMT+02:00) Athens' => 'Europe/Istanbul',
 '(GMT+02:00) Bucharest' => 'Europe/Bucharest',
 '(GMT+02:00) Cairo' => 'Africa/Cairo',
 '(GMT+02:00) Harare' => 'Africa/Johannesburg',
 '(GMT+02:00) Helsinki' => 'Europe/Helsinki',
 '(GMT+02:00) Istanbul' => 'Europe/Istanbul',
 '(GMT+02:00) Jerusalem' => 'Asia/Jerusalem',
 '(GMT+02:00) Kyiv' => 'Europe/Helsinki',
 '(GMT+02:00) Minsk' => 'Europe/Istanbul',
 '(GMT+02:00) Pretoria' => 'Africa/Johannesburg',
 '(GMT+02:00) Riga' => 'Europe/Helsinki',
 '(GMT+02:00) Sofia' => 'Europe/Helsinki',
 '(GMT+02:00) Tallinn' => 'Europe/Helsinki',
 '(GMT+02:00) Vilnius' => 'Europe/Helsinki',
 '(GMT+03:00) Baghdad' => 'Asia/Baghdad',
 '(GMT+03:00) Kuwait' => 'Asia/Riyadh',
 '(GMT+03:00) Moscow' => 'Europe/Moscow',
 '(GMT+03:00) Nairobi' => 'Africa/Nairobi',
 '(GMT+03:00) Riyadh' => 'Asia/Riyadh',
 '(GMT+03:00) St. Petersburg' => 'Europe/Moscow',
 '(GMT+03:00) Volgograd' => 'Europe/Moscow',
 '(GMT+03:30) Tehran' => 'Asia/Tehran',
 '(GMT+04:00) Abu Dhabi' => 'Asia/Muscat',
 '(GMT+04:00) Baku' => 'Asia/Tbilisi',
 '(GMT+04:00) Muscat' => 'Asia/Muscat',
 '(GMT+04:00) Tbilisi' => 'Asia/Tbilisi',
 '(GMT+04:00) Yerevan' => 'Asia/Tbilisi',
 '(GMT+04:30) Kabul' => 'Asia/Kabul',
 '(GMT+05:00) Ekaterinburg' => 'Asia/Yekaterinburg',
 '(GMT+05:00) Islamabad' => 'Asia/Karachi',
 '(GMT+05:00) Karachi' => 'Asia/Karachi',
 '(GMT+05:00) Tashkent' => 'Asia/Karachi',
 '(GMT+05:30) Chennai' => 'Asia/Calcutta',
 '(GMT+05:30) Kolkata' => 'Asia/Calcutta',
 '(GMT+05:30) Mumbai' => 'Asia/Calcutta',
 '(GMT+05:30) New Delhi' => 'Asia/Calcutta',
 '(GMT+05:45) Kathmandu' => 'Asia/Katmandu',
 '(GMT+06:00) Almaty' => 'Asia/Novosibirsk',
 '(GMT+06:00) Astana' => 'Asia/Dhaka',
 '(GMT+06:00) Dhaka' => 'Asia/Dhaka',
 '(GMT+06:00) Novosibirsk' => 'Asia/Novosibirsk',
 '(GMT+06:00) Sri Jayawardenepura' => 'Asia/Colombo',
 '(GMT+06:30) Rangoon' => 'Asia/Rangoon',
 '(GMT+07:00) Bangkok' => 'Asia/Bangkok',
 '(GMT+07:00) Hanoi' => 'Asia/Bangkok',
 '(GMT+07:00) Jakarta' => 'Asia/Bangkok',
 '(GMT+07:00) Krasnoyarsk' => 'Asia/Krasnoyarsk',
 '(GMT+08:00) Beijing' => 'Asia/Hong_Kong',
 '(GMT+08:00) Chongqing' => 'Asia/Hong_Kong',
 '(GMT+08:00) Hong Kong' => 'Asia/Hong_Kong',
 '(GMT+08:00) Irkutsk' => 'Asia/Irkutsk',
 '(GMT+08:00) Kuala Lumpur' => 'Asia/Singapore',
 '(GMT+08:00) Perth' => 'Australia/Perth',
 '(GMT+08:00) Singapore' => 'Asia/Singapore',
 '(GMT+08:00) Taipei' => 'Asia/Taipei',
 '(GMT+08:00) Ulaan Bataar' => 'Asia/Irkutsk',
 '(GMT+08:00) Urumqi' => 'Asia/Hong_Kong',
 '(GMT+09:00) Osaka' => 'Asia/Tokyo',
 '(GMT+09:00) Sapporo' => 'Asia/Tokyo',
 '(GMT+09:00) Seoul' => 'Asia/Seoul',
 '(GMT+09:00) Tokyo' => 'Asia/Tokyo',
 '(GMT+09:00) Yakutsk' => 'Asia/Yakutsk',
 '(GMT+09:30) Adelaide' => 'Australia/Adelaide',
 '(GMT+09:30) Darwin' => 'Australia/Darwin',
 '(GMT+10:00) Brisbane' => 'Australia/Brisbane',
 '(GMT+10:00) Canberra' => 'Australia/Sydney',
 '(GMT+10:00) Guam' => 'Pacific/Guam',
 '(GMT+10:00) Hobart' => 'Australia/Hobart',
 '(GMT+10:00) Melbourne' => 'Australia/Sydney',
 '(GMT+10:00) Port Moresby' => 'Pacific/Guam',
 '(GMT+10:00) Sydney' => 'Australia/Sydney',
 '(GMT+10:00) Vladivostok' => 'Asia/Vladivostok',
 '(GMT+11:00) Magadan' => 'Asia/Magadan',
 '(GMT+11:00) New Caledonia' => 'Asia/Magadan',
 '(GMT+11:00) Solomon Is.' => 'Asia/Magadan',
 '(GMT+12:00) Auckland' => 'Pacific/Auckland',
 '(GMT+12:00) Fiji' => 'Pacific/Fiji',
 '(GMT+12:00) Kamchatka' => 'Pacific/Fiji',
 '(GMT+12:00) Marshall Is.' => 'Pacific/Fiji',
 '(GMT+12:00) Wellington' => 'Pacific/Auckland',
 '(GMT+13:00) Nuku\'alofa' => 'Pacific/Tongatapu',

);

 

windows-time-zone.zip

发表在 php | php timezone已关闭评论