第 2 章:安装与环境搭建
2.1 环境准备
在安装 nanomsg / NNG 之前,确保系统已安装以下工具:
| 工具 | 用途 | 最低版本 |
|---|---|---|
| C 编译器 | 编译源码 | GCC 4.8+ / Clang 3.5+ |
| CMake | 构建系统 | 3.6+ |
| Git | 克隆源码 | 任意 |
| Make | 构建工具 | GNU Make 3.81+ |
2.1.1 Ubuntu / Debian
sudo apt update
sudo apt install -y build-essential cmake git
2.1.2 CentOS / RHEL
sudo yum groupinstall -y "Development Tools"
sudo yum install -y cmake3 git
# cmake3 需要通过 alternatives 设置
sudo alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20
2.1.3 macOS
xcode-select --install
brew install cmake
2.1.4 验证环境
gcc --version
cmake --version
git --version
2.2 安装 nanomsg
2.2.1 从源码编译
# 克隆仓库
git clone https://github.com/nanomsg/nanomsg.git
cd nanomsg
# 创建构建目录
mkdir build && cd build
# 配置
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
# 编译(-j 指定并行数)
make -j$(nproc)
# 运行测试(可选)
ctest --output-on-failure
# 安装
sudo make install
sudo ldconfig
2.2.2 CMake 常用选项
| 选项 | 默认值 | 说明 |
|---|---|---|
CMAKE_INSTALL_PREFIX | /usr/local | 安装路径 |
CMAKE_BUILD_TYPE | Debug | 构建类型:Debug / Release |
NN_ENABLE_DOC | ON | 是否生成文档 |
NN_TESTS | ON | 是否编译测试 |
NN_ENABLE_SP | ON | 是否编译可扩展性协议 |
Release 构建(推荐用于生产):
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DNN_TESTS=OFF
make -j$(nproc)
sudo make install
2.2.3 包管理器安装
# Ubuntu / Debian
sudo apt install -y libnanomsg-dev
# macOS
brew install nanomsg
# Fedora
sudo dnf install -y nanomsg-devel
注意:包管理器版本可能滞后于 GitHub 仓库,建议从源码编译以获取最新特性。
2.2.4 验证安装
# 检查头文件
ls /usr/local/include/nanomsg/
# 检查库文件
ls /usr/local/lib/libnanomsg*
# 编写测试程序
cat > /tmp/test_nn.c << 'EOF'
#include <stdio.h>
#include <nanomsg/nn.h>
#include <nanomsg/pair.h>
int main() {
int sock = nn_socket(AF_SP, NN_PAIR);
if (sock >= 0) {
printf("nanomsg OK! Socket fd = %d\n", sock);
nn_close(sock);
} else {
printf("nanomsg FAILED: %s\n", nn_strerror(nn_errno()));
}
return 0;
}
EOF
cc /tmp/test_nn.c -lnanomsg -o /tmp/test_nn
/tmp/test_nn
# 输出: nanomsg OK! Socket fd = 3
2.3 安装 NNG
2.3.1 从源码编译
# 克隆仓库
git clone https://github.com/nanomsg/nng.git
cd nng
# 创建构建目录
mkdir build && cd build
# 配置
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_BUILD_TYPE=Release
# 编译
make -j$(nproc)
# 运行测试(可选)
ctest --output-on-failure
# 安装
sudo make install
sudo ldconfig
2.3.2 NNG CMake 常用选项
| 选项 | 默认值 | 说明 |
|---|---|---|
CMAKE_INSTALL_PREFIX | /usr/local | 安装路径 |
CMAKE_BUILD_TYPE | Debug | 构建类型 |
NNG_TESTS | ON | 是否编译测试 |
NNG_TOOLS | ON | 是否编译命令行工具 |
NNG_ENABLE_TLS | OFF | 是否启用 TLS 支持 |
NNG_TRANSPORT_TCP | ON | 是否编译 TCP 传输 |
NNG_TRANSPORT_IPC | ON | 是否编译 IPC 传输 |
NNG_TRANSPORT_INPROC | ON | 是否编译 inproc 传输 |
NNG_TRANSPORT_WS | ON | 是否编译 WebSocket 传输 |
NNG_STATIC_LIB | OFF | 是否编译静态库 |
启用 TLS 的构建:
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DNNG_ENABLE_TLS=ON \
-DNNG_STATIC_LIB=ON \
-DCMAKE_INSTALL_PREFIX=/usr/local
make -j$(nproc)
sudo make install
2.3.3 验证 NNG 安装
# 检查头文件
ls /usr/local/include/nng/nng.h
# 检查库文件
ls /usr/local/lib/libnng*
# 检查工具
nngcat --help
nngcat 是 NNG 自带的命令行调试工具,可用于快速测试消息传递:
# 终端 1:监听
nngcat --rep --listen tcp://*:5555
# 终端 2:发送
nngcat --req --dial tcp://localhost:5555 --data "Hello"
2.3.4 编写 NNG 测试程序
#include <stdio.h>
#include <nng/nng.h>
#include <nng/protocol/pair0/pair.h>
int main() {
nng_socket sock;
int rv = nng_pair0_open(&sock);
if (rv == 0) {
printf("NNG OK! Socket opened successfully.\n");
nng_close(sock);
} else {
printf("NNG FAILED: %s\n", nng_strerror(rv));
}
return 0;
}
cc test_nng.c -lnng -o test_nng
./test_nng
# 输出: NNG OK! Socket opened successfully.
2.4 语言绑定
虽然 nanomsg / NNG 的核心是 C 库,但社区提供了丰富的语言绑定。
2.4.1 语言绑定一览
| 语言 | nanomsg 绑定 | NNG 绑定 | 安装方式 |
|---|---|---|---|
| Python | pynanomsg | pynng | pip install pynng |
| Go | go-nanomsg | mangos | go get |
| Rust | nanomsg.rs | nng-rs | Cargo |
| Java | jnanomsg | — | Maven |
| Node.js | nanomsg | — | npm install nanomsg |
| C#/.NET | NNanomsg | NNG.NET | NuGet |
| Ruby | nanomsg | — | gem |
| Haskell | nanomsg-haskell | — | cabal |
| Erlang | enm | — | rebar |
| Lua | lua-nanomsg | — | luarocks |
2.4.2 Python 绑定示例
安装 pynng:
pip install pynng
REQ/REP 示例:
# server.py
from pynng import Rep0
with Rep0(listen='tcp://*:5555') as sock:
while True:
msg = sock.recv()
print(f"Received: {msg.decode()}")
sock.send(b'OK')
# client.py
from pynng import Req0
with Req0(dial='tcp://localhost:5555') as sock:
sock.send(b'Hello, NNG!')
reply = sock.recv()
print(f"Reply: {reply.decode()}")
2.4.3 Go 绑定示例(mangos)
package main
import (
"fmt"
"log"
"time"
mangos "github.com/nanomsg/mangos"
"github.com/nanomsg/mangos/protocol/req"
"github.com/nanomsg/mangos/transport/tcp"
)
func main() {
sock, err := req.NewSocket()
if err != nil {
log.Fatal(err)
}
defer sock.Close()
sock.AddTransport(tcp.NewTransport())
if err = sock.Dial("tcp://localhost:5555"); err != nil {
log.Fatal(err)
}
if err = sock.Send([]byte("Hello, mangos!")); err != nil {
log.Fatal(err)
}
reply, err := sock.Recv()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Reply: %s\n", string(reply))
}
2.4.4 Rust 绑定示例(nng-rs)
use nng::{Protocol, Socket};
fn main() -> Result<(), nng::Error> {
let sock = Socket::new(Protocol::Pair0)?;
sock.dial("tcp://localhost:5555")?;
sock.send(b"Hello, NNG!")?;
let msg = sock.recv()?;
println!("Reply: {}", String::from_utf8_lossy(&msg));
Ok(())
}
Cargo.toml 依赖:
[dependencies]
nng = "1.0"
2.5 静态库构建
在某些场景下(嵌入式部署、简化分发),需要将 nanomsg / NNG 编译为静态库。
2.5.1 nanomsg 静态库
cd nanomsg
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
make -j$(nproc)
# 静态库位置
ls libnanomsg.a
链接静态库:
cc myapp.c -L. -lnanomsg -lpthread -lrt -o myapp
2.5.2 NNG 静态库
cd nng
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DNNG_STATIC_LIB=ON
make -j$(nproc)
# 静态库位置
ls libnng.a
2.5.3 在 CMake 项目中使用
cmake_minimum_required(VERSION 3.10)
project(myapp C)
find_package(nng REQUIRED)
add_executable(myapp main.c)
target_link_libraries(myapp nng::nng)
2.5.4 使用 pkg-config
# nanomsg
cc myapp.c $(pkg-config --cflags --libs nanomsg) -o myapp
# NNG
cc myapp.c $(pkg-config --cflags --libs libnng) -o myapp
2.6 自定义安装路径
如果需要安装到非标准路径(如用户目录),可在 CMake 中指定:
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/local/nng
make -j$(nproc)
make install
# 使用时指定路径
cc myapp.c -I$HOME/local/nng/include \
-L$HOME/local/nng/lib \
-lnng \
-Wl,-rpath,$HOME/local/nng/lib \
-o myapp
2.6.1 设置环境变量
# 添加到 ~/.bashrc 或 ~/.zshrc
export NNG_HOME=$HOME/local/nng
export PATH=$NNG_HOME/bin:$PATH
export CPATH=$NNG_HOME/include:$CPATH
export LIBRARY_PATH=$NNG_HOME/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=$NNG_HOME/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=$NNG_HOME/lib/pkgconfig:$PKG_CONFIG_PATH
2.7 CMake 集成模板
推荐的项目结构:
myproject/
├── CMakeLists.txt
├── src/
│ └── main.c
└── third_party/
└── nng/ # NNG 源码(可选,作为子模块)
方式 1:系统安装的库
cmake_minimum_required(VERSION 3.10)
project(myproject C)
set(CMAKE_C_STANDARD 11)
find_package(nng REQUIRED)
add_executable(myproject src/main.c)
target_link_libraries(myproject nng::nng)
方式 2:FetchContent 自动下载
cmake_minimum_required(VERSION 3.14)
project(myproject C)
include(FetchContent)
FetchContent_Declare(
nng
GIT_REPOSITORY https://github.com/nanomsg/nng.git
GIT_TAG v1.8.0
)
FetchContent_MakeAvailable(nng)
add_executable(myproject src/main.c)
target_link_libraries(myproject nng)
方式 3:Git Submodule
git submodule add https://github.com/nanomsg/nng.git third_party/nng
cmake_minimum_required(VERSION 3.10)
project(myproject C)
add_subdirectory(third_party/nng)
add_executable(myproject src/main.c)
target_link_libraries(myproject nng)
2.8 常见问题排查
2.8.1 编译错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
CMake not found | 未安装 CMake | apt install cmake |
nng.h: No such file | 头文件未安装或路径错误 | 检查 CMAKE_INSTALL_PREFIX |
undefined reference to nng_* | 链接器找不到库 | 添加 -lnng 或检查 LIBRARY_PATH |
libnng.so: cannot open shared object | 运行时找不到动态库 | sudo ldconfig 或设置 LD_LIBRARY_PATH |
2.8.2 TLS 编译问题
# 如果启用 TLS 报错找不到 mbedTLS
sudo apt install -y libmbedtls-dev
# 或使用 OpenSSL
cmake .. -DNNG_ENABLE_TLS=ON -DNNG_TLS_ENGINE=openssl
2.8.3 运行时权限问题
# IPC 使用 Unix Socket 时,可能需要目录权限
mkdir -p /tmp/nng_sockets
chmod 777 /tmp/nng_sockets
2.9 注意事项
版本选择:nanomsg 最新稳定版为 1.1.5(2018 年),NNG 最新版为 1.8+(2024 年活跃开发中)。新项目务必使用 NNG。
ABI 兼容性:NNG 的 ABI 在大版本间不保证向后兼容,升级时需重新编译应用。
交叉编译:嵌入式场景需要交叉编译时,需在 CMake 中指定工具链文件:
cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake
2.10 扩展阅读
上一章:第 1 章:nanomsg / NNG 概述 | 下一章:第 3 章:可扩展性协议详解