OSI模型与TCP/IP协议体系结构
什么是网络的体系结构
网络体系结构即指网络的层次结构和每层所使用协议的集合
网络采用分而治之的方法设计,将网络的功能划分为不同的模块,以分层的形式有机组合在一起。 每层实现不同的功能,其内部实现方法对外部其他层次来说是透明的。每层向上层提供服务,同时使用 下层提供的服务 两类非常重要的体系结构:OSI与TCP/IP
两类网络体系(OSI与TCP/IP)
网络接口层
1.什么是数据帧
就是数据链路层的协议数据单元,它包括三部分:帧头,数据部分,帧尾。其中,帧头和帧尾包含一些 必要的控制信息,比如同步信息、地址信息、差错控制信息等;数据部分则包含网络层传下来的数据, 比如IP数据包,等等。
2.数据帧的组成
2.网络层
1.什么是数据包
包(Packet)是TCP/IP协议通信传输中的数据单位,一般也称“数据包”。在局域网中,“包”是包含在“帧”里 的。 包(Packet):在包交换网络里,单个消息被划分为多个数据块,这些数据块称为包,它包含发送者和接 收者的地址信息。这些包然后沿着不同的路径在一个或多个网络中传输,并且在目的地重新组合
2.数据包的组成
3.传输层
共同点:同为传输层协议 不同点:
TCP:有连接,可靠
UDP:无连接,不保证可靠
1.TCP (传输控制协议)
TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通信(即数据无误、数据无 丢失、数据无失序、数据无重复到达的通信)
适用情况:
1.适合于对传输质量要求较高,以及传输大量数据的通信。
2.在需要可靠数据传输的场合,通常使用TCP协议
3.MSN/QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议
2.UDP(用户数据包协议)
UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不 需要进行连接,所以可以进行高效率的数据传输。 适用情况:
1.发送小尺寸数据(如对DNS服务器进行IP地址查询时)
2.在接收到数据,给出应答较困难的网络中使用UDP。(如:无线网络) 3.适合于广播/组播式通信中。
4.MSN/QQ/Skype等即时通讯软件的点对点文本通讯以及音视频通讯通常采用UDP协议
5.流媒体、VOD、VoIP、IPTV等网络多媒体服务中通常采用UDP方式进行实时数据传输
4.应用层
TCP通信
服务器
#include <stdio.h>
#include "net.h"
#include <string.h>
#include <stdlib.h>
//自定义监听有人连接的函数
//参数1:IP地址
//参数2:端口号
//返回值:成功返回监听的socket对象,失败返回-1
int tcp_server(const char * ip,int port);
int tcp_server(const char * ip,int port)
{
//1.创建流式socket对象
int listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0) {
perror("socket error");
return -1;
}
printf("socket ok\n");
//2.设置自己的地址
struct sockaddr_in myAddr;
memset(&myAddr,'\0',sizeof(myAddr));
myAddr.sin_family=AF_INET;
myAddr.sin_port=htons(port);
myAddr.sin_addr.s_addr=inet_addr(ip);
//3.绑定自己的地址
if(bind(listenfd,(struct sockaddr *)&myAddr,sizeof(myAddr))<0)
{
perror("bind error");
return -1;
}
printf("bind ok\n");
//4.监听是否有人连接
if(listen(listenfd,5)<0)
{
perror("listen error");
return -1;
}
printf("listen ok\n");
return listenfd;
}
//2.和客户端进行通信的函数
//参数1:连接好的socket对象
//返回值:通信结束返回0,不结束1
int tcp_com(int newfd);
int tcp_com(int newfd)
{
char buf[20]={'\0'};
int n=recv(newfd,buf,sizeof(buf),0); //接收客户端传过来的数据
printf("n===%d\n",n);
printf("read:<<<%s",buf);
if(strncasecmp(buf,"quit",4)==0)
return 0;
return 1;
}
int main(int argc, const char *argv[])
{
if(argc<3)
{
perror("please input app ip port\n");
return -1;
}
//1.监听是否有人连接
int listenfd=tcp_server(argv[1],atoi(argv[2]));
//2.接收连接
//2.1 不获得客户端的地址
//int newfd=accept(listenfd,NULL,NULL);
//2.2获得
struct sockaddr_in client;
2.客户端程序
memset(&client,'\0',sizeof(client));
int len=sizeof(client);
int newfd=accept(listenfd,(struct sockaddr *)&client,&len);
if(newfd<0)
{
perror("accept error");
return -1;
}
printf("accept ok
ip=%sport=%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
//3.和客户端进行通信
while(1)
{
int n=tcp_com(newfd);
if(n==0) break;
}
//4.通信结束,关闭socket对象
close(newfd);
close(listenfd);
return 0;
}
客户端
#include <stdio.h>
#include "net.h"
#include <string.h>
#include <stdlib.h>
//1.自定义连接服务器的函数
//参数1:ip地址 const char * ip
//参数2:端口号 int port
//返回值:连接成功,返回socket对象,失败返回-1
int tcp_connect(const char * ip,int port);
int tcp_connect(const char * ip,int port)
{
//1.创建socket对象(流式套接字)
int tcp_socket=socket(AF_INET,SOCK_STREAM,0);
if(tcp_socket<0)
{
perror("socket error");
return -1;
}
printf("socket ok\n");
//2.设置服务器的IP地址和端口号
struct sockaddr_in server;
memset(&server,'\0',sizeof(server));
server.sin_family=AF_INET; //地址族
server.sin_port=htons(port); //网络字节序的转换
server.sin_addr.s_addr=inet_addr(ip);//网络字节序的IP
//3.请求连接
if(connect(tcp_socket,(struct sockaddr *)&server,sizeof(server))<0)
{
perror("connect error"); return -1;
}
printf("connect ok\n");
return tcp_socket;
}
//自定义和服务器通信的函数
//参数1:连接好的socket对象
//返回值:通信结束返回0,不结束返回1
int tcp_com(int tcp_socket);
int tcp_com(int tcp_socket)
{
char buf[20]={'\0'};
printf("xiaoming<<<<");
fgets(buf,sizeof(buf),stdin);//从键盘进行输入包含'\n'
int n=send(tcp_socket,buf,strlen(buf),0);//发送数据给服务器
printf("n=%d\n",n);
if(strncasecmp(buf,"quit",5)==0)
{
return 0;
}
return 1;
}
int main(int argc, const char *argv[])
{
if(argc<3)
{
printf("please input app ip port\n");
return -1;
}
//1.连接服务器
int tcp_socket=tcp_connect(argv[1],atoi(argv[2]));
while(1)
{
//2.跟服务器进行通信
int res=tcp_com(tcp_socket);
if(res==0) //返回0表示通信结束
{
printf("通信结束");
break;
}
}
//3.关闭socket
close(tcp_socket);
return 0;
}
SQlite3
SQLite的源代码是C,其源代码完全开放。SQLite第一个Alpha版本诞生于2000年5月。 他是一个轻量级 的嵌入式数据库。
SQLite有以下特性:
零配置一无需安装和管理配置;
储存在单一磁盘文件中的一个完整的数据库;
数据库文件可以在不同字节顺序的机器间自由共享;
支持数据库大小至2TB;
足够小,全部源码大致3万行c代码,250KB;
比目前流行的大多数数据库对数据的操作要快;
在Linux安装sqlite3
SQlite3 点命令
c r e a t e
insert into
select
update
delete
alter
Sqlite3C语言的接口
sqlite3_open()
int sqlite3_open(char *path, sqlite3 **db); 功能:打开sqlite数据库
path: 数据库文件路径
db: 指向sqlite句柄的指针
返回值:成功返回0(SQLITE_OK),失败返回错误码(非零值)
sqlite3_exec()
int sqlite3_exec(sqlite3 *db, const char *sql, sqlite3_callback callback, void *data, char **errmsg); 功能:执行SQL操作
db:数据库句柄
sql:SQL语句
callback:回调函数 (主要在select语句) 其他一般设置NULL
data NULL
errmsg:错误信息指针的地址
返回值:成功返回0,失败返回错误码
sqlite3_close()
sqlite3_get_table() 不使用回调函数
不使用回调函数执行SQL语句
int sqlite3_get_table(sqlite3 *db, const char *sql, char ***resultp, int*nrow,
int *ncolumn, char **errmsg); 功能:执行SQL操作
db:数据库句柄
sql:SQL语句
resultp:用来指向sql执行结果的指针
nrow: 满足条件的记录的数目
ncolumn:每条记录包含的字段数目
errmsg:错误信息指针的地址
返回值:成功返回0,失败返回错误码
使用回调函数
typedef int (*sqlite3_callback)(void *para, int f_num, char *f_value[], char *f_name[]);
typedef int (*sqlite3_callback)(void *para, int f_num, char **f_value, char **f_name);
功能:每找到一条记录自动执行一次回调函数
para:传递给回调函数的参数
f_num:记录中包含的字段数目 (列数) f_value:包含每个字段值的指针数组 (列值)
f_name:包含每个字段名称的指针数组 (列名) 返回值:成功返回0,失败返回-1