服务器
server.c
#include "./server.h"
int main(int argc, char const *argv[])
{
//1.数据库初始化
sqlite3 *sql_db=proc_init();
//检验命令行参数个数
if (3 != argc)
{
printf("Usage : %s <IP> <PORT>\n", argv[0]);
exit(-1);
}
//3. 创建套接字-填充服务器网络信息结构体-绑定-监听
int sockfd = socket_bind_listen(argv);
//4. 用来保存 客户端 信息的结构体
struct sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(client_addr));
socklen_t client_addr_len = sizeof(client_addr);
//epoll函数实现io多路复用
//创建一个epoll
int epfd=epoll_create(10);//内部数字没意义,填大于零数字即可
if (-1==epfd) ERRLOG("epoll_create error");
struct epoll_event event; //事件结构体
event.events=EPOLLIN;//监控读;EPOLLIN读;EPOLLOUT写
event.data.fd=sockfd;//监控的套接字;将sockfd套接字加入监控集合
// -添加
if (0!=epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&event))
ERRLOG("epoll_ctl ADD error");
struct epoll_event revents[256]={0};//监控的最大个数,创建监控表,用于epoll_wait函数使用
int ret_epoll=0;//承接epoll_wait函数返回值,返回准备好的文件描述符个数
int i=0;//用于循环筛选准备好的文件描述符
int accept_fd;
int ret;
while (1)
{
ret_epoll= epoll_wait(epfd,revents,sizeof(revents),-1);// -1:不关心超时
if(-1==ret_epoll)
ERRLOG("epoll wait error");
else
{
//for循环遍历监控表
for ( i = 0; i <ret_epoll; i++)
{
if (revents[i].data.fd==sockfd)
{
//阻塞等待客户端连接--一旦有客户端连接就会解除阻塞
accept_fd=accept(sockfd,(struct sockaddr *)&client_addr, &client_addr_len);
if (-1==accept_fd) ERRLOG("accept error");
/* inet_ntoa 32位网络字节序二进制地址转换成点分十进制的字符串; ntohs将无符号2字节整型 网络-->主机 */
printf("客户端[%s : %d]连接\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
event.events=EPOLLIN;//监控读;EPOLLIN读;EPOLLOUT写
event.data.fd=accept_fd;//监控的套接字
// -添加
if (0!=epoll_ctl(epfd,EPOLL_CTL_ADD,accept_fd,&event))
ERRLOG("epoll_ctl ADD error");
}
else
{
//说明有客户端发来消息了
accept_fd = revents[i].data.fd;
//接收客户端发来的数据
ret=child_do(accept_fd,sql_db);
if (88==ret)
{
// - 删除
if (0!=epoll_ctl(epfd,EPOLL_CTL_DEL,accept_fd,&event))
ERRLOG("epoll_ctl ADD error");
close(accept_fd);
}
}
}
}
}
//关闭监听套接字 一般不关闭
close(sockfd);
return 0;
}
// 1. 数据库初始化 ---打开数据文件、建表
sqlite3 *proc_init(void)
{
//1. 打开数据库文件
sqlite3 *sql_db=NULL;
int ret=sqlite3_open(FILEname,&sql_db);
if (ret!=SQLITE_OK)
{
printf("打开数据库文件 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
//2. 建表
/* IF NOT EXISTS 表不存在则创建 表存在则直接使用,而不是报错;引号里面sql语句后面不用加分号*/
//管理员-密码
char sql_rbuf[256]="CREATE TABLE IF NOT EXISTS root(id INT PRIMARY KEY, pass TEXT)";
ret=sqlite3_exec(sql_db,sql_rbuf,NULL,NULL,NULL);
if (ret!=SQLITE_OK)
{
perror("建root表 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
memset(sql_rbuf,0,sizeof(sql_rbuf));
//使用查询函数
sprintf(sql_rbuf,"SELECT * FROM root WHERE id=%d",123456);
char **result={0}; // 结果集
int row = 0; // 行数
int column = 0; // 列数
/*
会将 查询的到的结果的 行数写到row的地址里 列数写到column的地址里
让 result 指向 sqlite3_get_table 申请的结果集的内存空间
*/
//查询结果的函数 /结果集 /行数 /列数 /错误信息
ret=sqlite3_get_table(sql_db,sql_rbuf,&result,&row,&column,NULL);
if (ret!=SQLITE_OK)
{
perror("查询 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
if (0==row)
{
memset(sql_rbuf,0,sizeof(sql_rbuf));
sprintf(sql_rbuf,"INSERT INTO root(id,pass) VALUES(%d,'%s')",123456,"123456");
ret=sqlite3_exec(sql_db,sql_rbuf,NULL,NULL,NULL);
if (ret!=SQLITE_OK)
{
perror("注册 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
}
//用户-密码-性别-年龄-住址-薪资-职务
char sql_ubuf[256]="CREATE TABLE IF NOT EXISTS user(id INT PRIMARY KEY,pass TEXT,name TEXT,sex TEXT,age INT,pay INT,job TEXT)";
ret=sqlite3_exec(sql_db,sql_ubuf,NULL,NULL,NULL);
if (ret!=SQLITE_OK)
{
perror("建user表 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
return sql_db;
}
//3. 创建套接字-填充服务器网络信息结构体-绑定-监听
int socket_bind_listen(const char *argv[])
{
// 1.创建套接字 /IPV4 /TCP
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if (-1==sockfd) ERRLOG("创建套接字 失败");
// 2.填充服务器网络信息结构体
struct sockaddr_in server_addr;
memset(&server_addr,0,sizeof(server_addr));//清空
server_addr.sin_family=AF_INET; // IPV4
/*端口号 atoi字符串转换成整型数; htons将无符号2字节整型 主机-->网络*/
server_addr.sin_port=htons(atoi(argv[2]));
/*ip地址; inet_addr字符串转换成32位的网络字节序二进制值*/
server_addr.sin_addr.s_addr=inet_addr(argv[1]);
//结构体长度
socklen_t server_addr_len=sizeof(server_addr);
//3. 将套接字和网络信息结构体绑定
if (-1==bind(sockfd,(struct sockaddr *)&server_addr,server_addr_len))
ERRLOG("结构体绑定 失败");
//4. 将套接字设置成被动监听状态
if (-1 == listen(sockfd, 10))
ERRLOG("listen error");