一个经典的 socket 服务器/客户端消息推送模型。服务端监听端口,客户端发起连接,收到服务端推送消息。用法:server <端口> <推送信息>
,client <服务器地址> <服务端口>
。
源码点击下列文件名查看:server.c
,serverWrapper.c
,serverWrapper.h
,client.c
均为 Linux 程序。个中细节在 csdn、cnblogs 等各大博客上早就解释一清二楚,不在此赘述了。
其中一个关于代码可移植性的问题略突出 —— socket 的 SO_REUSEADDR
SO_REUSEPORT
这两个地址端口的复用属性。参看爆栈网高票回答
SO_REUSEADDR
:- BSD 上的 socket 设置
SO_REUSEADDR
后,(a) 首先可以无视之前绑定的进入TIME_WAIT
状态的 socket 来强行绑定到同一个地址端口,(b) 其次可以复用野卡 IP0.0.0.0
,把野卡 IP 和其他一般本地 IP 视为完全不同的地址,以便绑定到同一个端口(例如,两个不同的 socket 可以分别绑定0.0.0.0:80
和192.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
设置地址端口独占,避免被“偷用”;
- BSD 上的 socket 设置
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:没有此选项。