• 2010-11-13

    Linus又骂人stupid

    Views: 41840 | 15 Comments

    最近, 有位用户向 bugzilla.redhat.com 报告他用 Fedora Linux 上网听 MP3 音乐时, 会播放出奇怪的声音. Linux 之父 Linus Torvalds 参与了讨论, 并最终找出原因, 竟然是 glibc 升级了 memcpy() 函数, 导致浏览器的 Abobe Flash Player 插件出现问题.

    这真是太强大了, 竟然能从上网听音乐追查到几乎是软件最底层基础的 memcpy() 函数! 如果你想知道他是如何一步一步找出 BUG 的原因的, 可以自己去看贴. (我个人不得不表示非常佩服他们敏锐的技术嗅觉和科学精神!)

    这个 BUG 的原因是, 某位 glibc 贡献者(看邮件地址应该是 Intel 公司的某华裔工程师)提交了一个速度更快的 memcpy() 函数的实现并被采纳. 但是, 这个速度更快的 memcpy() 并没有像它的前一个版本一样对源内存和目的内存重叠的情况做兼容, 所以导致了 Flash 插件出问题.

    Continue reading »

    Posted by ideawu at 2010-11-13 16:00:08
  • 2010-08-21

    C语言解析JSON

    Views: 31713 | 1 Comment

    最近一个 C/C++ 项目要用到 JSON, 所以选用了 json-c 库. C 语言不像 PHP/Python 等动态语言, 可以无缝地将 JSON 数据结构转为自身的数据结构, 所以操作起来会有些麻烦.

    首先是数据结构. 在 json-c 里, 所有的 JSON 数据结构都是 json_object 类型, 然后这个 json_object 结构有一个 type 字段, 表明当前的对象是什么类型, 比如整数, 数组, 字符串等等. 没错, 大多数动态语言都是用类似的方法处理动态类型.

    json-c 有自己的引用计数的内存管理机制, json_object_get() 函数用于手动地增加对象的引用计数, 相对地, json_object_put() 用于手动地减少引用计数. 要使用 json-c 必须非常明白每一个函数, 是否会增加或者减少对象的引用计数, 以避免内存泄露.

    Continue reading »

    Posted by ideawu at 2010-08-21 21:45:56
  • 2010-07-16

    经典的”服务器最多65536个连接”误解

    Views: 60237 | 9 Comments

    "因为TCP端口号是16位无符号整数, 最大65535, 所以一台服务器最多支持65536个TCP socket连接." - 一个非常经典的误解! 即使是有多年网络编程经验的人, 也会持有这个错误结论.

    要戳破这个错误结论, 可以从理论和实践两方面来.

    理论

    系统通过一个四元组来唯一标识一条TCP连接. 这个四元组的结构是{local_ip, local_port, remote_ip, remote_port}, 对于IPv4, 系统理论上最多可以管理2^(32+16+32+16), 2的96次方个连接.

    因为对于同一台服务器来说, 一般只有一个 local_ip, 那么, 同一台服务器可以管理 2^(16+32+16) 个连接. 而一个服务(进程, 如 Nginx 进程)一般只监听一个 local_port, 那么, 同一台服务就可以管理 2^(32+16) 个连接. 而如果从一台远端机器(所谓的 client)来连接这台服务器上的一个服务, 那么 local_ip, local_port, remote_ip 这3个变量是固定的, 那么, 就只能建立 2^16=65536 个连接了. 这就是经典的误解的来源!

    如果不仅仅考虑TCP, 则是一个五元组, 加上协议号(TCP, UDP或者其它).

    Continue reading »

    Posted by ideawu at 2010-07-16 16:44:50
  • 2010-06-11

    连连看游戏开发实践(1) – 算法

    Views: 15861 | No Comments

    从本篇文章开始, 我将写一序列游戏开发的文章, 讲述做一个连连看游戏的例子, 既锻炼自己, 也帮助别人. 最终, 游戏会加上网络功能.

    连连看算法

    如图, 为了找出A, B两点之间的连接路径, 首先过这两点作4条线段, 线段的两端便是地图边缘, 两条与横坐标轴平行, 另两条与纵坐标轴平行. 先考虑与横坐标轴平行的两条.

    在两条线段上各取一点C和D, 此两点处在一条与纵坐标轴平行的直线上. 那么, ACDB这条路径便是一条可能的A, B两点的连通路径.

    Continue reading »

    Posted by ideawu at 2010-06-11 17:01:13
  • 2009-10-12

    编写基于TCP的应用程序

    Views: 28741 | 1 Comment

    这似乎是一个非常简单的话题, 就跟"是个人就能做网站"一样, 你可能也认为"是个人就能写使用TCP socket的网络程序". 不过, 下面介绍的几个基本的原理的做法, 你可能并没有理解.

    TCP是一种流式的协议, 简单的说, TCP不检查数据的语义, 更不会检查数据的边界, 而应用层一般使用的是报文协议, 所以会有所谓的"粘包""拆包"问题. 为此, 产生了一些特定的用法和模式.

    任何应用程序, 都必须先进行报文协议设计. 虽然有些人捂上耳朵叫道"我不需要报文协议", 但是, 他还是需要进行报文协议设计. 有几种方式可用来设计报文协议:

    1. 明确声明报文数据的长度.
    2. 使用分隔符.
    3. 发送方发送完数据后关闭连接.

    第3种是socket的特定用法.

    报文设计方法1: 明确声明报文数据的长度

    此种方法一般较为常用, 因为兼容性好性能高. 一会介绍方法2的时候你就知道了. 一般会在数据的最前面用固定的几个字节存储一个二进制整数, 显示后面的数据的长度. 不过, 这是比较接近硬件底层报文协议设计. 应用层一般不这样, 在数据的前端固定几个字节存储ASCII数字, 前端补字符串'0', 或者在数字串后面跟换行符'\n', 这是一种和2的方法的混用.

    报文设计方法2: 使用分隔符

    前面介绍方法1的时候提过了, 使用分隔符来分隔报文, 然后在一般的语言都有 split() 函数, 用起来简单. 不过, 使用分隔符有一个缺点, 就是要进行数据转义, 避免报文数据中带有分隔符, 那就不好了. 此种方法还有一个缺点, 就是要遍历每一个字节, 查找分隔符, 性能不好. 介绍方法1的时候, 因为我们明确知道是数字串后面跟换行符, 所以不需要转义, 不会有转义性能损失, 同时数字串一般很短, 也可以忽略遍历性能损失.

    报文设计方法3: 发送方发送完数据后关闭连接

    这是 HTTP 1.0 采用的方式, HTTP 1.0 会在发送完响应后关闭连接(当然, 发送完请求后不能关闭连接, 所以可想而知, HTTP 1.0 必然使用方法1或者方法2, 你可以自己去学习了解). 这种方法不常用, 因为适用场景非常窄, 功能差.

    Continue reading »

    Posted by ideawu at 2009-10-12 15:15:52
  • 2009-08-22

    C语言类函数宏的参数

    Views: 17121 | No Comments

    宏很有用, 小心别上瘾.

    1. Stringification, 把参数作为C字符串, "#".

    #define M(a) #a

    M(hello) => "hello"

    2. Concatenation, 字面替换和拼接, "##".

    #define M(a) a ## _b

    M(hello) => hello_b

    ## 两边可以放空白字符和注释.

    参考: Red Hat Enterprise Linux 3: Using cpp, the C Preprocessor

    Posted by ideawu at 2009-08-22 13:47:33
|<<<5678910111213>>>| 12/13 Pages, 77 Results.