一个经典的 socket 服务器/客户端消息推送模型。服务端监听端口,客户端发起连接,收到服务端推送消息。用法:server <端口> <推送信息>client <服务器地址> <服务端口>

源码点击下列文件名查看:server.cserverWrapper.cserverWrapper.hclient.c 均为 Linux 程序。个中细节在 csdn、cnblogs 等各大博客上早就解释一清二楚,不在此赘述了。

其中一个关于代码可移植性的问题略突出 —— socket 的 SO_REUSEADDR SO_REUSEPORT 这两个地址端口的复用属性。参看爆栈网高票回答

  • SO_REUSEADDR:

    • BSD 上的 socket 设置 SO_REUSEADDR 后,(a) 首先可以无视之前绑定的进入 TIME_WAIT 状态的 socket 来强行绑定到同一个地址端口,(b) 其次可以复用野卡 IP 0.0.0.0,把野卡 IP 和其他一般本地 IP 视为完全不同的地址,以便绑定到同一个端口(例如,两个不同的 socket 可以分别绑定 0.0.0.0:80192.168.1.1:80 而不出错);
    • macOS (MacOS X)、iOS 等:Darwin 是 BSD 近亲,XNU 提供与 BSD 相同的选项和期望行为;
    • Linux、Android 等:(a) 同样有无视 TIME_WAIT 而强行绑定的行为,(b) 但不存在同一端口上复用野卡 IP 的行为(野卡 IP 一定会和普通 IP 冲突,不分绑定先后顺序)
    • Windows,设置此项后 socket 无论如何都可以绑定到任意地址任意端口,可以通过 SO_EXCLUSIVEADDRUSE 设置地址端口独占,避免被“偷用”;
  • SO_REUSEPORT:

    • BSD:可以绑定任意多的 socket 到同一个地址和端口上,前提是先绑定的 socket 必须开启此项属性,后来的 socket 也设置了这个属性才能继续绑定;
    • macOS (MacOS X)、iOS 等:同 BSD;
    • (a) 3.9 版前的 Linux:没有此选项,但对发起 UDP 连接的客户端 socket 而言,可通过 SO_REUSEADDR 来弥补,达到多个服务同时使用一个地址端口发起请求的效果,绑定顺序同 BSD 一样要求先绑定的 socket 开启选项。(b) 3.9 版后的 Linux:有此选项,行为基本和 BSD 相同,但要求复用同一个端口的进程都有同样的 UID —— 防止被其他用户“偷用”;还有就是内核会尽量对同一端口上的多个 socket 平衡负载。Android 同 Linux。
    • Windows:没有此选项。