C++学习笔记

函数重载(Function Overloading)

定义:函数名相同,函数的参数列表包括参数的类型、参数的个数和参数的顺序,只要有一个不同就叫做参数列表不同。

1
2
3
4
5
// 解析XML字符串的函数族,支持int、char *和double三种类型。
// 返回值:0-成功,-1-失败。
int GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,int *out_Value);
int GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,char *out_Value);
int GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,double *out_Value);

C++编译器在编译的时候会根据参数列表的类型对函数进行重命名,比如:

1
int GetXMLBuffer_char_char_int(const char *in_XMLBuffer,const char *in_FieldName,int *out_Value);

Read More

C语言学习笔记

Hello World

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//文件名hello.c
//预处理指令
#include <stdio.h>

//入口函数
int main() {
printf("hello world");
return 0;
}


gcc hello.c
./a.out //输出hello world

C语言数据类型

  • 字符型(char):描述单个字符(一个字节),用半角的单引号包含起来,如’a’、’A’、’1’、’$’等,键盘能输入的英文和半角的符号都是字符。中文的汉字和标点符号是两个字节(GBK编码),不能算一个字符。
  • 整型(int):描述整数。
Read More

socket编程笔记

API介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

int socket(int af, int type, int protocol);
af 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF 是“Address Family”的简写,INET是“Inetnet”的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。
type 为数据传输方式,常用的有 SOCK_STREAM 和 SOCK_DGRAM
protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP


int bind(int sock, struct sockaddr *addr, socklen_t addrlen); //Linux
int bind(SOCKET sock, const struct sockaddr *addr, int addrlen); //Windows
sock 为 socket 文件描述符,
addr 为 sockaddr 结构体变量的指针,
addrlen 为 addr 变量的大小,可由 sizeof() 计算得出。


struct sockaddr_in{
sa_family_t sin_family; //地址族(Address Family),也就是地址类型
uint16_t sin_port; //16位的端口号
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用,一般用0填充
};



int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen); //Linux
int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen); //Windows


让套接字进入被动监听状态,所谓被动监听,是指当没有客户端请求时,套接字处于“睡眠”状态,只有当接收到客户端请求时,套接字才会被“唤醒”来响应请求。
int listen(int sock, int backlog); //Linux
int listen(SOCKET sock, int backlog); //Windows
sock 为需要进入监听状态的套接字
backlog 为请求队列的最大长度

请求队列
当套接字正在处理客户端请求时,如果有新的请求进来,套接字是没法处理的,只能把它放进缓冲区,待当前请求处理完毕后,再从缓冲区中读取出来处理。如果不断有新的请求进来,它们就按照先后顺序在缓冲区中排队,直到缓冲区满。这个缓冲区,就称为请求队列(Request Queue)。
缓冲区的长度(能存放多少个客户端请求)可以通过 listen() 函数的 backlog 参数指定,但究竟为多少并没有什么标准,可以根据你的需求来定,并发量小的话可以是10或者20
如果将 backlog 的值设置为 SOMAXCONN,就由系统来决定请求队列长度,这个值一般比较大,可能是几百,或者更多。
当请求队列满时,就不再接收新的请求,对于 Linux,客户端会收到 ECONNREFUSED 错误,对于 Windows,客户端会收到 WSAECONNREFUSED 错误。



int accept(int sock, struct sockaddr *addr, socklen_t *addrlen); //Linux
SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen); //Windows
返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字


Linux下的数据接收和发送

会将缓冲区 buf 中的 nbytes 个字节写入文件 fd,成功则返回写入的字节数,失败则返回 -1
ssize_t write(int fd, const void *buf, size_t nbytes);
fd 为要写入的文件的描述符,buf 为要写入的数据的缓冲区地址,nbytes 为要写入的数据的字节数。

会从 fd 文件中读取 nbytes 个字节并保存到缓冲区 buf,成功则返回读取到的字节数(但遇到文件结尾则返回0),失败则返回 -1
ssize_t read(int fd, void *buf, size_t nbytes);


Windows下的数据接收和发送
int send(SOCKET sock, const char *buf, int len, int flags);
int recv(SOCKET sock, char *buf, int len, int flags);

基本概念

socket缓冲区

每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。

write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是TCP协议负责的事情。

Read More

多线程

线程的概念

引入进程的目的,是为了使多道程序并发执行,以提高资源利用率和系统吞吐量;而引入线程,则是为了减小程序在并发执行时所付出的时空开销,
提高操作系统的并发性能。

线程最直接的理解就是“轻量级进程”,它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。
线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其
他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运
行中呈现出间断性。

线程的状态

  • 新建状态:
Read More