手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 免费部署 N8N 的 Zeabur 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP

What makes a good programmer?

本文来自nio's blog(nio?尼奥?黑客帝国?),原文如下:

What makes a good programmer?

Some casual surfing led me to this article from a couple of years ago, titled "How to recognize a good programmer". It was a nice read, but as many in the comments pointed out, the criteria the author set forth most likely describe himself and are not really useful as rules-of-thumb on how to recognize a good programmer.

It got me thinking though, on what are the attributes I consider useful in fellow programmers. So what makes a good programmer?

以下五项,按照优先级,你会怎样排序呢?

  • Security(安全性)
  • Maintainability(可维护性)
  • Usability(可用性)
  • Performance(性能)
  • LOC (lines-of-code) count(代码量)

作者认为最重要的是 usability,因为你开发的东西最终价值取决于最终用户。我们开发的目的是为了解决问题,如果解决不了问题,则说明项目是失败的。

 

php Socket 基础

纯参考,突然让我想起以前的ugia.cn提供的upu(还是ugu来着?不记得了)上传组件。
利用socket监听,然后上传,利用流来写入文件。值得参考一下,想着ASP可以利用 xmlhttp进行大文件上传,想来PHP应该也可以,啥时候研究一下。
以下内容就是socket的初学者要看的文章,我也要看。呵呵

内容如下,未做删减 http://phpsoho.com/article/php/200809/11-245.html
PHP使 用Berkley的socket库来创建它的连接。socket只不过是一个数据结构。你使用这个socket数据结构去开始一个客户端和服务器之间的会 话。这个服务器是一直在监听准备产生一个新的会话。当一个客户端连接服务器,它就打开服务器正在进行监听的一个端口进行会话。这时,服务器端接受客户端的 连接请求,那么就进行一次循环。现在这个客户端就能够发送信息到服务器,服务器也能发送信息给客户端。
产生一个Socket,你需要三个变量:一个协议、一个socket类型和一个公共协议类型。产生一个socket有三种协议供选择,继续看下面的内容来获取详细的协议内容。
定义一个公共的协议类型是进行连接一个必不可少的元素。下面的表我们看看有那些公共的协议类型。

表一:协议

名字/常量     描述
AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用在IPv4的地址
AF_INET6     与上面类似,不过是来用在IPv6的地址
AF_UNIX 本地协议,使用在Unix和Linux系统上,它很少使用,一般都是当客户端和服务器在同一台机器上的时候使用

表二:Socket类型

名字/常量     描述
SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
SOCK_SEQPACKET 这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
SOCK_RAW 这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包顺序

表三:公共协议

名字/常量     描述
ICMP 互联网控制消息协议,主要使用在网关和主机上,用来检查网络状况和报告错误信息
UDP      用户数据报文协议,它是一个无连接,不可靠的传输协议
TCP 传输控制协议,这是一个使用最多的可靠的公共协议,它能保证数据包能够到达接受者那儿,如果在传输过程中发生错误,那么它将重新发送出错数据包。
现 在你知道了产生一个socket的三个元素,那么我们就在php中使用socket_create()函数来产生一个socket。这个 socket_create()函数需要三个参数:一个协议、一个socket类型、一个公共协议。socket_create()函数运行成功返回一个 包含socket的资源类型,如果没有成功则返回false。
Resourece socket_create(int protocol, int socketType, int commonProtocol);
现在你产生一个socket,然后呢?php提供了几个操纵socket的函数。你能够绑定socket到一个IP,监听一个socket的通信,接受一个socket;现在我们来看一个例子,了解函数是如何产生、接受和监听一个socket。

$commonProtocol = getprotobyname(“tcp”);//使用公共协议名字来获取一个协议类型
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);//产生一个socket并且返回一个socket资源的实例
socket_bind($socket, ‘localhost’, 1337);//绑定socket到本地计算机
socket_listen($socket);//监听所有进来的socket连接
// More socket functionality to come

面这个例子产生一个你自己的服务器端。例子第一行

$commonProtocol = getprotobyname(“tcp”);

使用公共协议名字来获取一个协议类型。在这里使用的是TCP公共协议,如果你想使用UDP或者ICMP协议,那么你应该把 getprotobyname()函数的参数改为“udp”或“icmp”。还有一个可选的办法是不使用getprotobyname()函数而是指定 SOL_TCP或SOL_UDP在socket_create()函数中。
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
例子的第二行是产生一个socket并且返回一个socket资源的实例。在你有了一个socket资源的实例以后,你就必须把socket绑定到一个IP地址和某一个端口上。

socket_bind($socket, ‘localhost’, 1337);


在这里你绑定socket到本地计算机(127.0.0.1)和绑定socket到你的1337端口。然后你就需要监听所有进来的socket连接。

socket_listen($socket);


在第四行以后,你就需要了解所有的socket函数和他们的使用。

表四:Socket函数

函数名      描述
socket_accept() 接受一个Socket连接
socket_bind() 把socket绑定在一个IP地址和端口上
socket_clear_error() 清除socket的错误或者最后的错误代码
socket_close() 关闭一个socket资源
socket_connect() 开始一个socket连接
socket_create_listen() 在指定端口打开一个socket监听
socket_create_pair() 产生一对没有区别的socket到一个数组里
socket_create() 产生一个socket,相当于产生一个socket的数据结构
socket_get_option() 获取socket选项
socket_getpeername() 获取远程类似主机的ip地址
socket_getsockname() 获取本地socket的ip地址
socket_iovec_add() 添加一个新的向量到一个分散/聚合的数组
socket_iovec_alloc() 这个函数创建一个能够发送接收读写的iovec数据结构
socket_iovec_delete() 删除一个已经分配的iovec
socket_iovec_fetch() 返回指定的iovec资源的数据
socket_iovec_free() 释放一个iovec资源
socket_iovec_set() 设置iovec的数据新值
socket_last_error() 获取当前socket的最后错误代码
socket_listen() 监听由指定socket的所有连接
socket_read() 读取指定长度的数据
socket_readv() 读取从分散/聚合数组过来的数据
socket_recv() 从socket里结束数据到缓存
socket_recvfrom() 接受数据从指定的socket,如果没有指定则默认当前socket
socket_recvmsg() 从iovec里接受消息
socket_select() 多路选择
socket_send() 这个函数发送数据到已连接的socket
socket_sendmsg() 发送消息到socket
socket_sendto() 发送消息到指定地址的socket
socket_set_block() 在socket里设置为块模式
socket_set_nonblock() socket里设置为非块模式
socket_set_option() 设置socket选项
socket_shutdown() 这个函数允许你关闭读、写、或者指定的socket
socket_strerror() 返回指定错误号的详细错误
socket_write() 写数据到socket缓存
socket_writev() 写数据到分散/聚合数组

以上所有的函数都是PHP中关于socket的,使用这些函数,你必须把你的socket打开,如果你没有打开,请编辑你的php.ini文件,去掉下面这行前面的注释:

extension=php_sockets.dll

如果你无法去掉注释,那么请使用下面的代码来加载扩展库:

if(!extension_loaded(‘sockets’))
{
if(strtoupper(substr(PHP_OS, 3)) == “WIN”)
{
dl(‘php_sockets.dll’);
}else{
dl(‘sockets.so’);
}
}

如果你不知道你的socket是否打开,那么你可以使用phpinfo()函数来确定socket是否打开。你通过查看phpinfo信息了解socket是否打开。
查看phpinfo()关于socket的信息

◆ 产生一个服务器

现在我们把第一个例子进行完善。你需要监听一个指定的socket并且处理用户的连接。

$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337);
socket_listen($socket);
// Accept any incoming connections to the server
$connection = socket_accept($socket);
if($connection){
socket_write($connection, "You have connected to the socket...\n\r");
}

你应该使用你的命令提示符来运行这个例子。理由是因为这里将产生一个服务器,而不是一个Web页面。如果你尝试使用Web浏览器来运行这个脚本,那么很有可能它会超过30秒的限时。你可以使用下面的代码来设置一个无限的运行时间,但是还是建议使用命令提示符来运行。

set_time_limit(0);

在你的命令提示符中对这个脚本进行简单测试:

Php.exe example01_server.php

如果你没有在系统的环境变量中设置php解释器的路径,那么你将需要给php.exe指定详细的路径。当你运行这个服务器端的时候,你能够通过远程登陆(telnet)的方式连接到端口1337来测试这个服务器。

上面的服务器端有三个问题:

1. 它不能接受多个连接。
2. 它只完成唯一的一个命令。
3. 你不能通过Web浏览器连接这个服务器。

这个第一个问题比较容易解决,你可以使用一个应用程序去每次都连接到服务器。但是后面的问题是你需要使用一个Web页面去连接这个服务器,这个比较困难。你可以让你的服务器接受连接,然后些数据到客户端(如果它一定要写的话),关闭连接并且等待下一个连接。
在上一个代码的基础上再改进,产生下面的代码来做你的新服务器端:

// Set up our socket 
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337); //socket_bind() 把socket绑定在一个IP地址和端口上
socket_listen($socket);
// Initialize the buffer
$buffer = "NO DATA";
while(true) {
// Accept any connections coming in on this socket
$connection = socket_accept($socket);//socket_accept() 接受一个Socket连接
printf("Socket connected\r\n");
// Check to see if there is anything in the buffer
if($buffer != ""){
printf("Something is in the buffer...sending data...\r\n");
socket_write($connection, $buffer . "\r\n"); //socket_write() 写数据到socket缓存
printf("Wrote to socket\r\n");
}else {
printf("No Data in the buffer\r\n");
}
// Get the input
while($data = socket_read($connection, 1024, PHP_NORMAL_READ))//socket_read() 读取指定长度的数据
{
$buffer = $data;
socket_write($connection, "Information Received\r\n");
printf("Buffer: " . $buffer . "\r\n");
}
socket_close($connection); //socket_close() 关闭一个socket资源
printf("Closed the socket\r\n\r\n");
}

这个服务器端要做什么呢?它初始化一个socket并且打开一个缓存收发数据。它等待连接,一旦产生一个连接,它将打印“Socket connected”在服务器端的屏幕上。这个服务器检查缓冲区,如果缓冲区里有数据,它将把数据发送到连接过来的计算机。然后它发送这个数据的接受信 息,一旦它接受了信息,就把信息保存到数据里,并且让连接的计算机知道这些信息,最后关闭连接。当连接关闭后,服务器又开始处理下一次连接。


◆ 产生一个客户端


处理第二个问题是很容易的。你需要产生一个php页连接一个socket,发送一些数据进它的缓存并处理它。然后你有个处理后的数据在还顿,你能够发送你的数据到服务器。在另外一台客户端连接,它将处理那些数据。
下面的例子示范了使用socket:

// Create the socket and connect 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connection = socket_connect($socket,’localhost’, 1337);
while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) {
if($buffer == “NO DATA”) {
echo(“<p>NO DATA</p>”);
break;
}else{
// Do something with the data in the buffer
echo(“<p>Buffer Data: “ . $buffer . “</p>”);
}
}
echo(“<p>Writing to Socket</p>”);
// Write some test data to our socket
if(!socket_write($socket, “SOME DATA\r\n”)){
echo(“<p>Write failed</p>”);
}
// Read any response from the socket
while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)){
echo(“<p>Data sent was: SOME DATA<br> Response was:” . $buffer . “</p>”);
}
echo(“<p>Done Reading from Socket</p>”);

这个例子的代码演示了客户端连接到服务器。客户端读取数据。如果这是第一时间到达这个循环的首次连接,这个服务器将发送“NO DATA”返回给客户端。如果情况发生了,这个客户端在连接之上。客户端发送它的数据到服务器,数据发送给服务器,客户端等待响应。一旦接受到响应,那么 它将把响应写到屏幕上。

Tags: socket

PHP5.3的新特性(一):对象接口的变化

PHP V5和面向对象编程
改进后的静态方法与属性的处理方式
__callStatic()魔术方法
动态的静态调用
静态调用的晚绑定
标准PHP库
循环垃圾回收

» 阅读全文

Tags: splstack, doublylink, splqueue

一篇介绍招聘的文章:如何面试应届生求职者

看到PHP5研究室上这篇文章,总还是有点感慨的。特别是最后那几句话:还是在 ngacn 上看到的一句话,团队需要两种人,要么 NB 的,要么听话的。


原文地址:http://www.phpv.net/html/1696.html
作者:Platinum
内容如下:

为什么要招应届生?不是因为便宜,有人说还没跳过槽的人忠诚度能搞些,这也不尽然,有些人没经受过工作的压力,总以为自己碰巧找到个压力大的工作, 换换会好些。我的原因是……应届生好调教。在他们没有被各种枯燥乏味的工作折磨的以为写程序本来就这么 SB 之前好好洗洗脑子。


1、2、3 是基础题,4、5、6 问的是数据库操作,7 算是综合能力吧。

1. 进制运算

可以是让他模拟一些简单的字符串函数,类似 bin2hex、base_convert、base64_encode,或者单纯的,让他手动算一下 7 进制的 54321 显示为 9 进制是多少。

应该高中或者之前就能接触到 2 进制 10 进制之间的换算了吧,当然,他当时很可能没听懂。通常的情况,如果以前没留意这个问题但有理解能力的,可能能在几分钟的做出一些成功不成功的尝试。至少不应该很茫然。最糟糕的情况,连整数的最大值是多少都不知道,那就算了。

2. 描述一下常见的关于读取文件内容的操作,及各自的特点

应 该不用迟疑太久就把 file、fopen、file_get_contents、readfile 列出来。表现好点还可以提下 readfile 的流式读取不占内存之类的。如果看的教材太老,可能只会说 fopen。最糟糕的辩解是不说跟数据库打交道比较多,文件操作没怎么接触过,完全无视文件静态化的存在。

3. 怎么模拟一个 POST 表单提交

答 socket 或者 cURL 都可以。

4. 列举一些常规优化方式

正 确索引(就不强求完全理解多列索引了,最好能知道每个查询只能用到一个索引),知道索引提高查询速度、降低插入速度。正确的字段类型(能知道 char 和 varchar 的区别和优缺点)。text 类字段可以单放一个表用主键关联。总之他能说的越多越好。顺便问问他他所知道的最大处理能力是每秒多少条,哪怕是测试环境里的 benchmarking(今天看到份简历,号称三年工作经验,将半个月三万条插入形容为他所遇到的最高的负载,写在简历的醒目位置)。

5. “你知道,把时间存在数据库里有两种方法,一种是用时间戳,就是 PHP 函数 time() 产生的那种整数,另一种是 MySQL 里字段类型设成 datetime。那么,为什么一定要后一种方式?”

最简单的一个例子,如果存的是时间戳,你无法按类似“所有周三的数据”这种方式显示内容。这表明了他的学习阶段:是否接触了类似日志分析类的东西。因为这些是早晚都要接触到的。

6. 简单联表查询

有这么两个表

user 表:

id  name
1   张三
2   李四
3   王五
4   赵六

apple 表:

id  user  number
1   1     5
2   3     3
3   1     8
4   4     6
5   3     2
6   4     2

apple 表的 user 字段跟 user 表的 id 对应,一条 SQL 语句查出每个人都有多少苹果

如果他不知道 join,可能会这么写

SELECT user.name, SUM(apple.number) FROM user, apple WHERE user.id = apple.user GROUP BY user.id

正确答案应该是这样

SELECT user.name, SUM(apple.number) FROM user LEFT JOIN apple ON user.id = apple.user GROUP BY id

这两条语句的差别是,不用 join 无法显示出李四有 0 个苹果 -_-

7. 假设我们要做一个公交系统的常见服务,就是做查公交车怎么倒车的。假设完全由你自己来搞,我只关心最后结果,你会怎么做这个项目。说的越详细越好。

可能需要不断提示。考查一个人的做事能力,比方说他首先会想到需要数据,数据库应该怎么设计,有几个表,什么样的字段。
可 以加分的地方可以有这么几个点。给站名编 id,匹配数字的速度要远大于匹配字符串。站点之间要距离的数据,这样计算最优倒车路线应该能考虑到站数,倒车次数、距离等权值。如果很有远见,任意两点 之间的数据应该是提前算好的,比方说有 200 条公交线路和 2000 个站点,始发终点的组合可能是 2000 * 1000,每种线路可能有 1 - 6 种方案,有个表是来装这近一千万行结果的,如果有线路变化,再用本地的机器重新算一遍线路。这样整个系统才有实用价值。不然可能每次查询都需要耗费数秒或 者更长时间,只能当单机软件用。


这些题本身是交流的话题,而不是“做对 5 道以上我就招你”这种门槛。我面试时每道题都会给予充分的时间,如果他做不上来,也起码能判断他的思考方式,而忌讳说“如果你不知道就明说,咱们赶紧做下 一题”。同时也能观察出性格等方面。比方说第 6 题,有人把 SUM 写成 COUNT,我就问他你看看前面写的是否有问题,同时又怕太明显,又补充一句“也可能什么错误也没有、我在误导你,你自己判断”,于是他就不再理会、继续 接着写完整个 SQL。再综合他的其他一些表现,我的结论是此人主见极强的,我不会用。属于出了 BUG 第一念头是 BUG 在解释器上、做出来的程序跟产品需求不符时会说是你产品没说明白的那种。相反,我很欣赏那些在做完第一道题的 7 进制转换后还知道验算的,因为既然是笔算就很容易出错。我觉得这种人思考严谨、负责任。

其他的一些知识,比方说 memcache、SVN、单元测试这些,都属于经验问题,应届生很少需要接触到这些东西(甚至文件静态化也很少碰到),不像上面,我需要以此来判断面试者对编程是否已经入门。

还是在 ngacn 上看到的一句话,团队需要两种人,要么 NB 的,要么听话的。

Tags: 招聘, 应届生

有关客户端浏览器缓存的Http头介绍

做网站开发离不开缓存,缓存分好多种:服务器缓存,第三方缓存,浏览器缓存等。其中浏览器缓存是代价最小的,因为浏览器缓存依赖的是客户端,而几乎不耗费服务器端的资源。

让浏览器做缓存需要给浏览器发送指定的Http头,告诉浏览器缓存多长时间,或者坚决不要缓存。作为.net的程序员,其实我们一直都在用这种方 法,在OutputCache指令中指定缓存的Location为Client时,其实就是给浏览器发送了一个Http头,告诉浏览器这个Url要缓存多 长时间,最后修改的时间。

微软在OutputCacheModule中对这些缓存用到的Http头给我们进行了很好的封装,但是了解这些Http头可以更灵活的使用它们。

和客户端缓存相关的Http头有以下几个,分别是:
1. Expires:+过期时间
表示在指定时间后浏览器缓存失效,需要注意的是这儿的过期时间必须是HTTP格式的日期时间,其他的都会被解析成当前时间“之前”,缓存会马上过期,HTTP的日期时间必须是格林威治时间(GMT),而不是本地时间。举例:
Expires: Fri, 30 Oct 2009 14:19:41

使用Expires过期必须要求服务器的时间是正确的,否则发送的http头就会出问题,在windows服务下可以设置时间服务器来同步时间
2. Cache-control:
Cache-control直译成中文就是缓存控制,它的作用就是缓存控制,这个http头的值有几种。
1) max-age=[秒] — 执行缓存被认为是最新的最长时间。类似于过期时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过期时间,[秒]是一个数字,单位是秒:从请求时间开始到过期时间之间的秒数。
2) s-maxage=[秒] — 类似于max-age属性,除了他应用于共享(如:代理服务器)缓存
3) public — 标记认证内容也可以被缓存,一般来说: 经过HTTP认证才能访问的内容,输出是自动不可以缓存的;
4) no-cache — 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处);
5) no-store — 强制缓存在任何情况下都不要保留任何副本
6) must-revalidate — 告诉缓存必须遵循所有你给予副本的新鲜度的,HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,你高速缓存,你希望严格的遵循你的规则。
7) proxy-revalidate — 和 must-revalidate类似,除了他只对缓存代理服务器起作用
举例:
Cache-Control: max-age=3600, must-revalidate

很显然Cache-control可以提供比Expires更灵活的缓存控制,而且它不需要依赖于服务器时间。
在Asp.Net中微软把对Cache-control属性的设置封装到了HttpCachePolicy类中,我们可以通过Response.Cache来调用以下方法来做到对Cache-Control Http头值的控制:
Response.CacheControl;
Response.Cache.SetNoStore
Response.Cache.SetMaxAge
Response.Cache.SetProxyMaxAge
Response.Cache.SetRevalidation
           
3. Last-Modified/If-Modified-Since
这 两个Http头是一对,前者表示某个地址的最近更新时间,是服务器端响应给客户端的;而后者是客户端浏览器发送给服务器的,告诉web服务器客户端有一个 最后更改时间为什么时间的缓存,服务器端接收到If-Modified-Since头后则判断客户端缓存的这份url地址的缓存是否是最新的,如果是最新 的则服务器端直接给客户端返回HttpStatus 304,意思是说这个内容在你上次请求之后没有变化过,你直接用缓存就可以了;如果服务器发现url的最后更新时间比If-Modified-Since 的值要新,则会输出新的内容。

同样微软也为我们做了服务器端设置的封装,我们可以这样调用
Response.Cache.SetLastModified(DateTime)
Response.Cache.SetLastModifiedFromFileDependencies()

如果有更复杂的需求就需要自己处理了。

4. ETag/If-None-Match
ETag和Last-Modified类似,不过他发送的是一个字符串来标示url的版本,如果url变了则此标示也跟着变化,在浏览器发送If-None-Match时告诉浏览器内容已经变了,或者没变可以使用缓存。

Iis会自动给静态文件加上Etag,在文件发生改变时重新生成一个Etag,这样对于一个网站中的n多个静态文件如:样式表,小图片等,客户端只下载一次就够了,可以减轻负载。

在Asp.Net中我们可以用以下两个方法来设置
Response.Cache.SetETag(string)
Response.Cache.SetETagFromFileDependencies()

尽管微软为我们做了很多封装,但是我们还是需要详细的了解之后才可以用好这几个Http头。