7月 312013
 

测试办法:

1. 使用nc做一个server

nc -l localhost 8181

CTRL-Z

2. 使用nc做client

nc localhost 8181 </dev/zero

3. netstat -an |grep 8181

171008 就是读buffer的大小(约160KB), 1279872就是写buffer的大小(约1.2MB)

现在nc client被write给阻塞住了,如果nc client之发送小于 171008 + 1279872 的数据,则现在已经兴高采烈地quit了,然而,server端却连1个字节都没处理呢,如果在把server给杀掉,则这些数据就都算丢弃了。

 

 

 Posted by at 上午 12:09
7月 302013
 

引言

1. tcp是有read buffer和write buffer的,如何才能确保数据不会死在buffer里,虽然tcp是面向连接的可靠的协议,但是tcp没有可靠到这等程度,有些事情还是需要考应用层来保证的

 

正文

关于shutdown和close的一些说明:

1. 如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放。
2. 在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会影响到其它进程. 得自己理解引用计数的用法了. 有Kernel编程知识的更好理解了.
3. 只要TCP栈的读缓冲里还有未读取(read)数据,则调用close时会直接向对端发送RST。
4. shutdown与socket描述符没有关系,即使调用shutdown(fd, SHUT_RDWR)也不会关闭fd,最终还需close(fd)。
5. 可以认为shutdown(fd, SHUT_RD)是空操作,因为shutdown后还可以继续从该socket读取数据,这点也许还需要进一步证实。
6. 在已发送FIN包后write该socket描述符会引发EPIPE/SIGPIPE。
7. 当有多个socket描述符指向同一socket对象时,调用close时首先会递减该对象的引用计数,计数为0时才会发送FIN包结束TCP连接。shutdown不同,只要以SHUT_WR/SHUT_RDWR方式调用即发送FIN包。
8. SO_LINGER与close,当SO_LINGER选项开启但超时值为0时,调用close直接发送RST(这样可以避免进入TIME_WAIT状态,但破坏了TCP协议的正常工作方式),SO_LINGER对shutdown无影响。
9. TCP连接上出现RST与随后可能的TIME_WAIT状态没有直接关系,主动发FIN包方必然会进入TIME_WAIT状态,除非不发送FIN而直接以发送RST结束连接。
参考资料:
 Posted by at 下午 11:40
7月 172013
 

缘起

学习fastcgi的时候,多个fcgi进程的启动和管理是个无法回避的问题;有一个叫做spawn-fcgi的程序,可以启动多个php-cgi进程,并且同时accept同一个socket,因为spawn-fcgi和php-cgi是两个项目中的程序,那么他们是如何配合的如此默契的呢?

资料: http://redmine.lighttpd.net/projects/spawn-fcgi    其中主要是: http://redmine.lighttpd.net/projects/spawn-fcgi/repository/entry/trunk/src/spawn-fcgi.c

 

分析

从代码来看,spawn-fcgi负责lisent一个socket,然后开始fork指定数量的子进程,每个子进程中先把socket的fd复制到FCGI使用的fd(似乎是约定好的一个fd),然后就把后续的事情通过exec交给外部的进程(如:php-cgi)了

下面看一下PHP中fastcgi的相关逻辑, 文件 sapi/cgi/fastcgi.c 中的 int fcgi_init(void);函数体现了如何识别是否fastcgi的逻辑,大致意思为: 如果标准输入为一个socket(不是fileno),则认为是fastcgi,代码片段如下:

 

注意其中 getpeername(…)的使用,如果 errno == ENOTCONN 才可能认为是fastcgi,那么,如果刚好该socket处于连接状态不就不能视为fastcgi环境了吗?  或许吧

 

 Posted by at 下午 11:35
2月 162013
 

缘起

如何在不发起一个Http请求的情况下删除一个Httponly的cookie?

探索:

1. 虽然JS无法读取Httponly的cookie,那么JS是否可以设置或删除Httponly的cookie呢?

答案是否定的

2. 使用http-equiv类型的meta标签是可以设置cookie的,那么是否可以cache一个带有http-equiv类型的meta标签的页面来操作cookie呢?

http-equiv类型的meta标签只能设置、删除、修改非Httponly类型的cookie

分析:

分析1:

JS无法访问Httponly的cookie,其中包括三层含义:

  1. 无法读取
  2. 无法设置和修改
  3. 无法删除

如:

无法通过如下方式设置、修改或删除一个已存在的Httponly的cookie:

无法通过如下方式设置、修改或删除一个已存在的Httponly的cookie:

注意:或许你通过第一种方式在一个Httponly的cookie已存在的情况下设置了一个新的test cookie,那么基本上是因为两个test的domain或path不同;如:一个Httponly的cookie设置在a.test.com域下,而这时通过document.domain=”test.com”,将domain修改为了 test.com;这时候可以通过第一种方式设置一个testcookie,和原有的Httponly的cookie并不冲突

 

分析2:

HTML中有一个meta标签,其中的一个用法是http-equiv,如,可以通过如下方式设置cookie:

但是,测试发现,似乎无法通过JS创建meta标签的方式来设置cookie

分析3:

测试发现,无法通过meta标签来设置、修改、删除一个Httponly的cookie

 Posted by at 上午 1:36
1月 172013
 

Why https?

  1. 保证用户信息的传输安全。包括用户名、密码、cookie、用户保存的服务器端信息等等
  2. 很大程度上免遭DNS劫持

Why not https?

  1. 更多的cpu资源的消耗
  2. 证书校验的时间消耗
  3. 证书校验可能因一些问题导致验证失败
 Posted by at 下午 2:06
1月 112013
 

缘起:

使用php的file_get_contents(…) 函数从广州发送一个http请求到北京,该请求的请求头和响应头如下:

现在,从广州到北京的一次数据的往返时间(就是ping的时间)为34ms,请求的执行时间为6ms; 因为请求头和相应头都非常小,分别一次tcp数据包就够,这样的话,一次http请求时间为: 34 + 34 + 6 = 74ms , 而实际却稳定在108ms左右,还有大约34ms不知去向

分析

根据这个丢失的时间长度来看,大概是多了一次数据的发送和接收; 通过tcpdump抓包发现如下现象:

file_get_contents(…)中实现的http请求,首先把请求行发送出去,收到请求行数据包的ack包后继续发送后续的请求头; 这样的话就凭空多出一次网络时间,其各种原因,有时间再看看PHP源码中为何如此实现吧。

测试了一下curl,没有这个问题。

 Posted by at 下午 7:23
1月 092013
 

看了一下如下脚本:

一次IPv6支持的检测需要5ms+的时间,成本是比较大的,但是,同一个进程中只检测一次,所以对于httpd进程来讲,这个是没有问题的

 

 Posted by at 下午 3:05