0%

通用唯一识别码(英语:Universally Unique Identifier,简称 UUID)的标准型式包含 32 个 16 进制数字,以连字号分为五段,形式为 8-4-4-4-12 的 32 个字符。示例:

550e8400-e29b-41d4-a716-446655440000

接下来重点描述在开发中的使用及应用。

在 C++ 中的使用

C++ 原生(C++03、C++11/0x)并不支持 UUID。所以要想在 C++ 代码中生成 UUID,如果要求跨平台推荐使用第三方库 Boost UUID,要么结合各自的平台,使用系统 API。以下方法整理自互联网,除 Boost Uuid 和 libuuid 使用过之外,其他的未亲自试验。

UUID generation using Boost in C++

在 StackOverflow 上的一个例子:跳转链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

#include <boost/uuid/uuid.hpp> // uuid class
#include <boost/uuid/uuid_generators.hpp> // generators
#include <boost/uuid/uuid_io.hpp> // streaming operators etc.

int main()
{
boost::uuids::random_generator generator;

boost::uuids::uuid uuid1 = generator();
std::cout << uuid1 << std::endl;
boost::uuids::uuid uuid2 = generator();
std::cout << uuid2 << std::endl;

return 0;
}

如果以上例子满足不了你的需求,需要在更复杂的情景下使用,请移步 Boost Uuid 官方文档

Qt QUuid

参考来源

Qt 是一个跨平台的 C++ 编程框架,QUuid 类实现了 UUID 的生成、比较、转换等功能。

函数 QUuid createUuid(),可用于生成 UUID。示例如下:

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <QUuid>
#include <QString>

int main()
{
QUuid uuid = QUuid::createUuid();
std::cout << qPrintable(uuid.toString()) << std::endl;
return 0;
}

Linux 下生成 UUID

Shell

Unix/Linux 环境中大都有一个名为 uuidgen 的小工具,运行即可生成一个 UUID 到标准输出。读取文件 /proc/sys/kernel/random/uuid 即得UUID,例如:

cat /proc/sys/kernel/random/uuid

libuuid

参考来源

libuuid 是一个用于生成 UUID 的 C 库,具体用法参考 http://linux.die.net/man/3/libuuid,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <uuid/uuid.h>

int main(int argc, char **argv)
{
uuid_t uuid;
char str[36];

uuid_generate(uuid);
uuid_unparse(uuid, str);

printf("%s\n", str);

return 0;
}

在 Linux 下编译时需要链接 uuid 库

gcc -o uuid uuid.c -luuid

问题: 在什么系统下自带?在什么系统中需要另行安装?

在 Ubuntu 中,可以用下面的命令安装 libuuid:

sudo apt-get install uuid-dev

Windows 下生成 UUID

CoCreateGuid

参考来源

Windows 下提供了函数 CoCreateGuid 用于生成 GUID。需要使用的头文件是 #include <objbase.h>,需要链接的库是 ole32.lib,函数原型为:HRESULT CoCreateGuid(GUID *pguid); ,GUID 的原型为

1
2
3
4
5
6
7
typedef struct _GUID
{
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} GUID;

UuidCreate

参考来源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma comment(lib, "rpcrt4.lib")  // UuidCreate - Minimum supported OS Win 2000
#include <windows.h>
#include <iostream>

using namespace std;

int main()
{
UUID uuid;
UuidCreate(&uuid);
char *str;
UuidToStringA(&uuid, (RPC_CSTR*)&str);
cout<<str<<endl;
RpcStringFreeA((RPC_CSTR*)&str);
return 0;
}

在 Java 中使用

工作中偶尔会写一些 Java 的项目,所以也捎带整理一下。

在 MySQL 中

MySQL 本身是带有生成 uuid 功能的。也就是我们惯用的整数递增作为主键,其实是可以用 uuid 替代的。可以在一条记录插入之前写触发器,调用 UUID() 函数生成 uuid。

C/C++ 的 socket 编程。开篇

  1. socket 编程貌似是从 *nix 到的 windows?
  2. socket 编程源于 C,但 C++ 似乎并没有原生的支持,依旧是 C 语言下的 socket 编程?
  3. C++ 的网络编程,包含哪些具体的内容?单单是 socket 吗? socket 编程不应该是更接近 C 语言吗?

socket 编程,入门学习非常推荐吴秦的 Linux Socket编程(不限Linux)。当做学习 socket 编程的第一篇完全足够,甩开网上其他的帖子一万八千里,强烈推荐。本意是整理 socket 的学习笔记,但有上述帖子完全足够,在此只记录一些“边边角角”的零碎知识。

手册推荐:Beej’s Guide to Network Programming

htonl() 函数、htons() 函数

在吴秦的博客里重点强调了主机字节序(host byte order)与网络字节序(network byte order)的,上述两个函数就是用来实现两者之间的转换的。参考 Beej’s Guide to Network Programming 我们能够找到以下函数原型:

1
2
3
4
5
6
#include <netinet/in.h>

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

不需要死记硬背,函数的命名通俗易懂。强调一下,转换 ip 地址使用长整型转换函数,转换 port 使用短整型转换函数。我在码代码学习时,误用 htonl(6666); 转换端口编译通过,运行时也不报错,启动多个服务程序也不报错 ps 正常情况重复启动服务程序时会报错“端口已经占用”。

INADDR_ANY

详细解释参考 understanding INADDR_ANY for socket programming - c。在此只强调一点,INADDR_ANY 表示的是一个服务器上所有的网卡。

inet_pton() 函数

IP地址转换函数,可以在将 IP 地址在“点分十进制”和“二进制整数”之间转换。在 Beej’s Guide to Network Programming 我们找到的描述以及函数原型:

Convert IP addresses to human-readable form and back.

1
2
3
4
5
6
#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src,
char *dst, socklen_t size);

int inet_pton(int af, const char *src, void *dst);

强调一点,inet_pton() 同样支持 “localhost”。

inet_addr() 函数

Convert IP addresses from a dots-and-number string to a struct in_addr and back

1
2
3
4
5
6
7
8
9
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// ALL THESE ARE DEPRECATED! Use inet_pton() or inet_ntop() instead!!

char *inet_ntoa(struct in_addr in);
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);

我们可以看到其中的注释,这三个函数即将淘汰。

学习 libevent

疑问

  1. select() 函数第一个参数为什么要 maxfd+1?不理解 官方手册 中讲述 select() 低效的这段话:

    On the userspace side, …But on the kernel side,…

  2. 为什么在 Example: select()-based ROT13 server 中需要 make_nonblocking() ?为什么 Example: A low-level ROT13 server with Libevent 中需要 evutil_make_socket_nonblocking()

  3. setvbuf(stdout, NULL, _IONBF, 0); 的意义?

资源

最初步的认识,最简单的例子:使用libevent输出Hello

(niel)这里只提到了 strcut event_basestruct event。给出的简单示例代码里,有一处瑕疵: event_base_set() 函数属于过时的函数,在 2.0 之前的版本中配合 event_set() 使用,在 2.0 及其之后的版本中这两者被 event_new() 替代,所以作者混用 event_new() + event_base_set() 表明了作者并未多花时间学习。

接下来,我们可以学习一下:libevent入门教程:Echo Server based on libevent

(niel)这篇博客循序渐进,讲到了 strcut buffevent 及其相关操作。美中不足的是作者在介绍过程中穿插记录了自己的疑惑,新手读起来打破了学习的连贯性,本就在学习新知识,却也要困于作者的“泥潭”。只能说这真的只是作者的学习笔记,并未从读者的角度做考虑。总的来说,帖子很不错!初次学习时,这些问题的存在让人很难受,影响学习进度、学习动力;但熟悉作者讲的知识之后,这些问题反而才是“金子”,认真思考这些问题。

接下来推荐的学习资源就是官方手册了:Programming with Libevent

(niel)虽然是用英文写的,但阅读起来毫无障碍,很容易理解。marks C0、C1、R0 ~ R4、R8 认真阅读;R5、R6 重点关注了小部分函数,其余走马观花浏览了一下;R6a、R7、R9 三节没有看。开发过程中,查阅函数原型肯定是得翻这个手册的!

Libevent 官方文档学习笔记,这篇帖子可以看一看,和自己读英文手册理解的相互佐证。

Libevent学习笔记(一):基本使用,检验自己的学习成果。

总的来说,后面这两篇帖子并不适合用来学习。更多的定位于作者知识的整理,并不是面向新手的入门介绍。

2015年12月22日 14:48:52

这个标题《Makefile 自动生成》 8 号立的,拖到今天刚好两周。ps 2017/8/24 14:04:25 删改了 2/3 的内容,改为现在的标题。

一方面因为最近在忙别的工作,整理数据库表结构的;另一方面,是直到今天,对于自动生成 Makefile 操作依旧懵懵懂懂,在实际项目中无法使用,还是自己手动写 Makefile 文件。下面进入主题。

Makefile 自动生成,实际项目中接触到的工具有:easymake、cmake 和 autotools。 在这里只整理 autotools。

autotools 作为重点学习,所以发现了很多篇不错的帖子。

  1. 编译利器:大型项目如何使用Automake和Autoconf完成编译配置(ver+0.6) 内容很棒,却找不到好的排版,将其摘入自己博客
  2. 概念:GNU构建系统和Autotool实践:GNU构建系统 作者整理的真心不错,专业功底、语言描述、文章结构都很赞;
  3. 使用autotools生成Makefile学习笔记 不能当做一篇学习的帖子,其“常用功能分析”一节可以作为参考手册,认清知识点
阅读全文 »

2015年11月6日 16:57:34

最全的学习材料当然是 GCC 的官方文档。如果有耐心但是英语不好的话,可以参看一下 这个网站。先说

gcc/g++ 执行的四个过程:

  1. gcc -E 仅作预处理,即只激活预处理,不进行编译、汇编和链接 {通常以什么为后缀?}

    $gcc -E main.c -o main.i

  2. gcc -s 编译到汇编语言,不进行汇编和链接,即只激活预处理和编译,生成汇编语言

    $gcc -S main.i -o main.s #参数-S,大写

  3. gcc -c 编译、汇编到目标代码,不进行链接,即只激活预处理、编译和汇编功能,生成目标文件(.o)

    $gcc -c main.s -o main.o

  4. 生成,到执行文件 (根据依赖关系链接各目标文件,生成最终的执行程序)

    $gcc main.o printf1.o printf2.o -o main

阅读全文 »

2015年12月8日 16:48:31

此中测试代码见笔记 《Makefile入门》

Makefile 之执行过程

  1. 依次读取变量“MAKEFILES”定义的 makefile 文件列表
  2. 读取工作目录下的 makefile 文件(根据命名的查找顺序“GNUmakefile”,“makefile”,“Makefile”,首先找到那个就读取那个)
  3. 依次读取工作目录 makefile 文件中使用指示符“include”包含的文件
  4. 查找重建所有已读取的 makefile 文件的规则(如果存在一个目标是当前读取的某一个 makefile 文件,则执行此规则重建此 makefile 文件,完成以后从第一步开始重新执行)
  5. 初始化变量值并展开那些需要立即展开的变量和函数并根据预设条件确定执行分支
  6. 根据“终极目标”以及其他目标的依赖关系建立依赖关系链表
  7. 执行除“终极目标”以外的所有的目标的规则(规则中如果依赖文件中任一个文件的时间戳比目标文件新,则使用规则所定义的命令重建目标文件)
  8. 执行“终极目标”所在的规则
阅读全文 »

2016年1月4日 10:05:04

shell 及环境变量 -1.4 其他

参数置换

shell提供了参数置换能力以便用户可以根据不同的条件来给变量赋不同的值。参数置换的变量有四种,这些变量通常与某一个位置参数相联系,根据指定的位置参数是否已经设置类决定变量的取值,它们的语法和功能分别如下。

  • 变量=${参数-word}:如果设置了参数,则用参数的值置换变量的值,否则用 word 置换。即这种变量的值等于某一个参数的值,如果该参数没有设置,则变量就等于 word 的值。
  • 变量=${参数=word}:如果设置了参数,则用参数的值置换变量的值,否则把变量设置成 word 然后再用 word 替换参数的值。注意,位置参数不能用于这种方式,因为在 shell 程序中不能为位置参数赋值。
  • 变量=${参数?word}:如果设置了参数,则用参数的值置换变量的值,否则就显示 word 并从 shell 中退出,如果省略了 word,则显示标准信息。这种变量要求一定等于某一个参数的值,如果该参数没有设置,就显示一个信息,然后退出,因此这种方式常用于出错指示。
  • 变量=${参数+word}:如果设置了参数,则用 word 置换变量,否则不进行置换。
阅读全文 »

2016/3/16 12:17:18

汇总 3 篇。此处 shell 指工具,不涉及 shell 编程、脚本等知识。

shell 和简单操作

shell 简介

Shell 是什么呢? 确切地说,Shell 就是一个命令行解释器,它的作用就是遵循一定的语法将输入的命令加以解释并传给操作系统内核,它为用户提供了一个向 Linux 发送请求以便运行程序的接口,用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序。

Linux Shell的种类 很多,目前流行的 Shell 包括 ash、bash、ksh、csh、zsh 等,用户可以通过查看 /etc/shells 文件中的内容来查看自己主机中当前有哪些种类的 Shell。

阅读全文 »

2015年11月20日 14:31:06

从月初开始接触 linux 开发,真心是磕磕绊绊。简单的使用,查阅一些操作命令这些都不是问题,困难主要在于 linux 下的开发。

  1. 大学有一本 unix 的教材,至少看了前五章。自己也折腾安装过 linux 的系统,从 CentOS、Fedora 到 debian,安装后也简单的操作过,虽说没有任务驱动最终也不了了之。但多少不认生。
  2. 公司的开发环境是有几台 suse 的服务器,在不同的局域网里。远程连接上去进行开发。使用的工具是 Xbrowser,其中包括 Xshell、Xftp 等。最开始两天使用过其中的 XDMCP 以图形界面操作局域网 A 中一台服务器,唯一的感受就是卡,画面的操作很不流畅,严重影响使用体验。一开始使用 suse 企业版 10 远程图形界面操作一般,后来重装系统 open suse linux 10 之后,XDMCP 的操作体验变得很糟糕。
  3. XDMCP 的使用,需要在服务器上进行有关的设置。后来在 57(局域网B中服务器的 ip)服务器上开发,工作组成员都没有此服务器的 root 权限。再没有使用图形界面,使用 Xshell+Xftp,使用 Xshell 进行和开发有关的操作,使用 Xftp 进行文件的传输和文本的编辑。基本上就是在主机上使用 notepad++ 编辑代码,通过 Xftp 同步到服务器,在 Xshell 中进行编译、运行操作(还没有掌握 gdb,调试处于看错误输出,改项目源码的阶段)。在 Xftp 中可以直接打开服务器上的源码进行编辑保存操作,所以还是比较方便的。
  4. 目前阶段这种“拼凑”的开发方式还是足够用的,但能明显感觉到瓶颈。对 vim 的操作止于零,这个周末在家练习,一步步把 vim 搭建成开发环境。+ makefile文件 + gdb
  5. 有时间了补足一下 x- 系列的操作步骤,虽然简单,但当时在网上没找到有关的介绍,前后也花费了大半天时间。
阅读全文 »

2016/3/26 20:07:56

条件编译是应用较为广泛的一个概念,不限于编译器。但在这里,只讲如何在 VS2010 一个项目中使用条件编译实现不同的版本。

只放链接,以后再次用到时再做整理。