VmWare(虚拟机)通过软件模拟出来的计算机
Ubuntu linux操作系统的一个发行版。
嵌入式设备
1 | 机械手表 智能手表 |
操作系统
Linux
- 开源 免费
- 内核可剪裁
- linux一切皆文件
- linux的文件系统像是一颗倒置的树
- 多用户 多任务
一、linux基础指令
权限
sudo —临时获取超级用户的权限
su — 切换用户
1
2su --- 切换到root用户
su 用户名 --- 切换到指定的用户
1.导航命令
- pwd – print work dirctory — 打印当前的绝对路径
1 | hqyj@ubuntu:~$ |
- ls — 将指定目录下的内容输出到终端
1 | /:根目录 |
- cd — change dirctory — 改变路径
1 | cd 路径 --- 进入指定的路径 |
2.目录文件
mkdir – make directory
1
mkdir 目录文件名
rmdir – 删除空目录文件
1
rmdir 目录文件名
rm
1
rm -r 目录文件名 -- 删除目录文件
3.普通文件
touch – 创建普通文件
1
touch 普通文件名1 普通文件名2 。。。。。。
rm – 删除普通文件
1
rm 普通文件名
cat – 将普通文件的内容输出到终端
1
cat 普通文件名
4.复制和剪切
cp – copy 赋值
1
2cp 原文件名 目标文件名
cp -r 源目录文件名 目标目录文件名mv –move 剪切
1
mv 原文件名 目标文件名
clear — 清空终端
二、编辑器
1.vi(vim)编辑器
- 打开vi编辑器
1 | 终端输入:vi 1.c --- 使用vi编辑器打开1.c文件,如果1.c文件不存在则创建 |
- 命令行模式
1 | 移动光标:键盘上的上下左右键 |
- 命令行模式 ->插入模式(编辑模式)
1 | i:从当前光标之前开始插入 |
插入模式–>命令行模式 Esc
底行模式
1
2
3:w --- 保存
:q --- 退出
:wq --- 保存并退出
2.gedit
1 | gedit test.c |
三、编译器 – gcc
使用方法
1
2
3
4gcc 1.c --- 编译1.c 如果没有语法错误则生成可执行文件 ->默认a.out
./a.out
gcc test.c -o test
./可执行文件名预处理
1
2对原文件中的一些预处理指令(
gcc -E 1.c -o 1.i编译
1
2将预处理之后的文件转换汇编文件 ,检查语法。
gcc -S 1.c -o 1.s汇编
1
2将汇编文件转换成目标机器能够执行的二进制文件.o -- 目标文件
gcc -c 1.c -o 1.o链接
1
2将所有目标文件链接(库函数)在一起生成可执行文件。
gcc 1.o
四、指针
什么是什么?
1
2
3
4指针就是地址
地址:内存最小单元(字节)的编号 --一般用十六进制形式表示
1111 1111 1111 1111 1111 1111 1111 1111
FF FF FF FF指针变量
1
指针变量是变量占据内存空间用来保存地址
1.指针变量定义的一般形式
1 | <数据类型> * 指针变量名; |
2.指针的偏移
1 | P + 1 :向高地址偏移一个数据类型单位 |
作业:验证自己当前计算机采用那种存储方式(大端/小端)
1 | 小端:数据的低位保存到地址空间----小段字节序 |
3.函数指针
1 | 函数返回类型 (*指针变量名)(函数形参列表); |
1 | int Pubg(int x,int y,char* ch) |
1 | int (*pfunc)(int ,int ); |
1 | man:linux 提供一种帮助手册可以用来查询命令、库函数、系统调用函数的使用方法。 |
五、项目
云存储
1.基础功能
- 上传
- 下载
- 查询
- 断点续传(附加)
2.知识点
linux基础指令
C语言
目录IO(查询)
1
2opendir
readdir文件IO (上传/下载)
1
2
3
4
5open
read
write
lseek
closeLinux网络编程 — TCP服务器搭建
3.具体流程
服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18搭建TCP服务器 socket bind listen
等待连接 accept
等待处理请求
if(buf == "list")
{
查询目录信息 --->发客户端
}
else if(buf == "load")
{
打开对应文件
将文件数据发送给客户端
}
else if(buf == "upld")
{
创建文件
等待接收客户端发送文件数据
将接收到的文件数据写入本地文件
}客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18搭建TCP客户端
发起连 connect
发起请求
if(buf == "list")
{
//等待接收服务器发过来的目录信息
}
else if(buf == "load")
{
打开对应文件
接收文件数据
将接收到的文件数据写入本地文件
}
else if(buf == "upld")
{
打开文件
发送文件数据到服务器
}
在线翻译
TCP服务器 UPD服务器
sqlite3数据库
1
2sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev
2.使用库函数来操作数据库文件
#include <sqlite3.h>
gcc xxxxx.c -lsqlite3
打开数据库文件
1
2
3
4
5
6
7
8
9
10
11
12int sqlite3_open(char *path, sqlite3 **db);
功能:打开sqlite数据库
path: 数据库文件路径 //如果指定的文件不存在则创建
db: 指向sqlite句柄的指针
sqlite3 *db;
sqlite3_open("xxxx.db",&db)
返回值:成功返回0,失败返回错误码(非零值)关闭数据库文件
1
2
3
4
5
6int sqlite3_close(sqlite3 *db);
功能:关闭sqlite数据库
返回值:成功返回0,失败返回错误码打印错误信息
1
2
3
4const char *sqlite3_errmsg(sqlite3 *db);
返回值:返回错误信息执行sql语句
1
2
3
4
5
6
7
8
9int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback, void *para, char **errmsg);
功能:执行SQL操作
db:数据库句柄
sql:SQL语句
callback:回调函数 //在执行select查找时才需要该参数 ----》NULL
para:传递给回调函数的参数。
errmsg:错误信息指针的地址// --->NULL
返回值:成功返回0,失败返回错误码callback
1
2
3
4
5
6
7
8
9typedef int (*sqlite3_callback)(void *para, int f_num, char **f_value, char **f_name);
功能:每找到一条记录自动执行一次回调函数
para:传递给回调函数的参数
f_num:记录中包含的字段数目
f_value:包含每个字段值的指针数组
f_name:包含每个字段名称的指针数组
返回值:成功返回0,失败返回-11、IP地址 – 在网络当中唯一标识一台主机。
IPv4 –4字节–32bit
1
2
3点分十进制:192.168.6.23 --->字符串--->便于传播记忆
二进制:11000000 10101000 00000110 00010111
inet_addr("192.168.6.23");//将点分十进制的字符串表示的ip转换成网络字节序IPv6 –128bit
2、端口号 –port
标识主机当中的一个进程
unsigned short – 0-65535
1
2
3
4
51-1024:系统应用的端口
1025-5000:常用应用端口
5001-65535:用户端口
htons(6666) --- 将6666转换成网络字节序
htonl
3、字节序
主机字节序host byte order
小端字节序
1
数据的低位保存低地址空间 ---》低低小
大端字节序
1
数据的低位保存高地址空间
网络字节序 network byte order—大端
4.套接字
本质:网络进行通信的两个进程的端点的抽象,给应用进程提供使用各层协议的接口。
linux中的一种系统调用–>socket,通过socket可以使用内核当中集成各层网络协议。
是一种特殊的文件描述符—>套接字文件描述符
四、TCP服务器
1.TCP服务器/客户端搭建流程
- 服务器:socket->bind->listen->accept->read/write->close
- 客户端:socket-> connect->read/write->close
2.TCP服务器相关接口函数
socket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int socket(int domain, int type, int protocol);
功能:
在内核当中创建一个端点并且返回一个文件描述符指向该端点。
文件描述符:当前进程能够分配最小非负整数。
参数:
domain:地址协议族
AF_INET:ipv4
AF_INET6:ipv6
AF_UNIX:本地套接字
type:
SOCK_STREAM:提供有序、可靠、全双工、基于字节流数据的传输。---》唯一对应TCP
SOCK_DGRAM:唯一对应UDP
SOCK_RAM:原始套接字
protocol:
一般填0
返回值:
成功:返回一个文件描述符---》套接字文件描述符
失败:-1bind
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
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:
为socket创建的套接字绑定ip和端口、地址协议族。
参数:
sockfd:socket返回的文件描述符---》套接字文件描述符
addr:
struct sockaddr {//通用地址结构体
sa_family_t sa_family;
char sa_data[14];
}
struct sockaddr_in {//ipv4地址结构
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
addrlen:地址结构体的长度。
返回值:
成功:0
失败:-1listen
1
2
3
4
5
6
7
8
9
10
11
int listen(int sockfd, int backlog);
功能:将绑定的套接字挂起让内监听,并且设置监听队列。
参数:
sockfd:绑定之后的套接字
backlog:监听队列的长度 --- >0
返回值:
成功:0
失败:-1accept
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:从监听队列种拿出队列的第一个请求并且返回一个新的文件描述符与该请求对应。
参数:
sockfd:监听之后的套接字
addr :保存客户端的ip地址 ---->NULL
addrlen:ipv4地址结构体的长度 ---->NULL
socklen_t addrlen = sizeof(struct sockaddr_in);
accept(sockfd,xxxxxx,&addrlen);
返回值:
成功:返回的一个新的文件描述符(连接套接字)与连接的客户端一一对应
失败:-1
注意:当read函数去读accept返回的连接套接字时如果连接套接字对应的缓冲中没有数据那么read会阻塞直到有数据返回实际读到的字节数。
如果read返回值为0代表客户端断开连接read/write
close
connect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:
将sockfd所引用的套接字连接到addr所指定的服务器。
参数:
sockfd:socket创建的套接字文件描述符
addr:服务器地址
addrlen:服务器地址结构体的大小
返回值:
成功:0
失败:-1
作业1:编写tcp客户端(分享)
练习:编写TCP服务器和客户端,客户端连接成功之后,服务器给客户端发送一张图片。
3、TCP服务器模型
tcp服务器
1
2
3
4
5
6
7socket();
bind();
listen();
accept();
read()/write();
close();循环服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16socket();
bind();
listen();
while(1)
{
accept();
while(1)
{
read()/write();
}
}
close();
gg=G:vi自动调整缩进多进程并发服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16socket();
bind();
listen();
while(1)
{
accept();
pid_t pid = fork();
if(0 == pid)
{
while(1)
{
read()/write();
}
}
}多线程并发服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23socket();
bind();
listen();
while(1)
{
connfd = accept();
pthread_t tid;
pthread_create(&tid,NULL,pfunc,&connfd);
pthread_detach(tid);
}
void *pfunc(void *arg)
{
int connfd = *(int *)arg;
while(1)
{
read()/write();
}
}
netstat -apn | grep "6666"
wireshark ---抓包工具
sudo apt-get install wireshark
作业1:编写文件传输服务器(TCP) ,查询目录下内容。
作业2:编写时间服务器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17创建套接字
绑定
监听
等待连接
while(1)
{
获取系统时间发送给客户端;
}
//////
创建套接字
发起连接
while(1)
{
接收服务器发送过来时间信息
}分享:TCP三次握手四次挥手,并且分析TCP协议头
五、UDP服务器
1、UDP服务器搭建流程
1
2
3
4socket(AF_INET,SOCK_DGRAM,0)//创建套接字
bind()//绑定
recvfrom()//等待接收数据2、UDP客户端的的搭建流程
1
2
3socket(AF_INET,SOCK_DGRAM,0)//创建套接字
sendto()//发送数据到指定的地址3、UDP相关接口函数
recvfrom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:接收对端发送的消息,并且将对端的地址信息保存到src_addr所指向的结构体。
参数:
sockfd:套接字文件描述符
buf:接收数据的缓冲区
len:要从sockfd指定的缓冲读取len个字节的数据
flags:0
src_addr:保存对端地址
addrlen:对端地址结构体的长度
socklen_t addrlen = sizeof(struct sockaddr_in);
recvfrom(xxx,xxx,xxx,xxx,xxx,&addrlen)
返回值:
成功:返回实际接收到的字节数。
失败:-1
注意:recvfrom是一个阻塞函数。sendto
1
2
3
4
5
6
7
8
9
10
11
12
13
14ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:利用sockfd将buf里面的前len个字节发送到dest_addr所指定的服务器/客户端去。
参数:
sockfd:套接字文件描述符
buf:发送缓冲区
len:发送的字节数
flags:0
dest_addr:对端的地址
addrlen:对端地址结构体的长度
返回值:
成功:返回实际发送的字节数
失败:返回-1
文件IO
man 手册第二页
open
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
功能:站在内核个角度打开一个文件,并且返回一个文件描述符,该文件描述指向打开的文件。
文件描述符:是当前系统可分配的最小的、非负的整数。
0:标准输入
1:标准输出
2:标准错误
参数:
pathname:文件名及路径
flags :设置打开文件的权限必须包含以下三个选项之一
{
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
}
O_CREAT:如果打开的文件不存在则创建
注意:一旦flags选择了O_CREAT那么open函数必须要传第三个参数mode
mode:文件创建的权限(0777)
返回值:
成功:返回文件描述符
失败:-1read
1
2
3
4
5
6
7
8
9
10
11
12
ssize_t read(int fd, void *buf, size_t count);
功能:从fd所指向的文件中读取count个字节的数据到部分所指向的缓冲区
参数:
fd:已经打开的文件描述符
buf:缓冲区首地址
count:要读取的字节数
返回值:
成功:返回实际读到的字节数
注意:如果read返回0代表读到了文件的末尾
失败:返回-1write
1
2
3
4
5
6
7
8
ssize_t write(int fd, const void *buf, size_t count);
功能:将buf缓冲里面的前count个字节的数据写入fd所指向的文件。
参数:
返回值:
成功返回实际写入的字节数
失败返回-1close
目录IO
opendir
1
2
3
4
5
6
7
8
DIR *opendir(const char *name);
功能:
参数:
返回值:readdir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:
参数:
返回值:
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /*保存目标目录中某一个文件名 */
};套接字属性
getsockopt()
setsockopt()
1 |
|
level
SOL_SOCKET
optname optval类型 SO_BROADCAST 允许发送广播数据 int SO_DEBUG 允许调试 int SO_DONTROUTE 不查找路由 int SO_ERROR 获得套接字错误 int SO_KEEPALIVE 保持连接 int SO_LINGER 延迟关闭连接 struct linger SO_OOBINLINE 带外数据放入正常数据流 int SO_RCVBUF 接收缓冲区大小 int SO_SNDBUF 发送缓冲区大小 int SO_RCVLOWAT 接收缓冲区下限 int SO_SNDLOWAT 发送缓冲区下限 int SO_RCVTIMEO 接收超时 struct timeval SO_SNDTIMEO 发送超时 struct timeval SO_REUSEADDR 允许重用本地地址和端口 int SO_TYPE 获得套接字类型 int SO_BSDCOMPAT 与BSD系统兼容 int IPPROTO_IP
optname optval类型 IP_ADD_MEMBERSHIP 将指定IP加入到组播组中 struct ip_mreq IP_MULTICAST_IF 允许开启组播报文的接口 struct ip_mreq IPPRO_TCP
optname optval类型 TCP_MAXSEG TCP最大数据段的大小 int TCP_NODELAY 不使用Nagle算法 int