本文共 13460 字,大约阅读时间需要 44 分钟。
1.main.c文件
要做的事有: 1.初始化客户登录信息表 2.检查启动参数和捕捉线程退出信号 3.定义和初始化线程池 4.初始化TCP 5.创建epoll和用epoll监听sfd 6.进入功能界面 6.(1)判断退出标志位是否改为1,是就进入退出程序 6.(2)若不退出程序,用while(1)监听epoll 6.(3)若现在没有新的sfd连接服务器,给新连接的sfd先来登录,主线程承接登录验证作用#include "../include/queue.h"#include "../include/head.h"#include "../include/threadpool.h"#include "../include/mainthread.h"#include "../include/childthread.h"#include "../include/register_login.h"//设置全局变量退出,用来表示主线程的退出标志int exitflag = 0;void sigFunc(int sigNum){ printf("signal%d is coming\n",sigNum); //主线程收到退出信号,修改退出标志位值,0代表正常运行,1代表退出 exitflag = 1;}int main(int argc,char *argv[]){ //1.初始化客户登录信息表,结构体login_Flag_List存储连接的sfd和连接状态 memset(login_Flag_List,0,sizeof(Login_Flag_t)*CLIENT_NUM); //2.检查启动参数和捕捉线程退出信号 // ./main ip port threadNum ARGS_CHECK(argc,4); //捕捉信号,SIGUSR1为线程退出发出的信号 signal(SIGUSR1,sigFunc); //接受开启的线程数 int threadNum = atoi(argv[3]); //3.定义和初始化线程池 ThreadPool_t threadPool; memset(&threadPool,0,sizeof(threadPool)); //初始化线程池 threadPoolInit(&threadPool,threadNum); //启动线程池 threadPoolStart(&threadPool); //4.初始化TCP int sfd = 0; tcpInit(argv[1],argv[2],&sfd); //5.创建epoll和用epoll监听sfd int epfd = epoll_create(1); epfdAddfd(sfd,epfd); //初始化epoll监听的参数 /* epfdAddfd(exitPipe[0],epfd); */ struct epoll_event evs[2]; int newFd = 0; int readyNum = 0; //6.进入功能界面 while(1) { //6.(1)判断退出标志位是否改为1,是就进入退出程序 if(1 == exitflag) { pNote_t pNote = (pNote_t)calloc(threadPool.threadNum,sizeof(Note_t)); pthread_mutex_lock(&threadPool.Queue.mutex); for(int i =0;i< readyNum; ++i) { if(sfd == evs[i].data.fd)//若有新的sfd连接请求到服务器 { newFd = accept(sfd,NULL,NULL);//接受sfd epfdAddfd(newFd,epfd);//加入监听集合 for(int j=0;j clientFd = evs[i].data.fd; queueInsert(&threadPool.Queue,pNote); pthread_cond_signal(&threadPool.Queue.cond); pthread_mutex_unlock(&threadPool.Queue.mutex); } } } } } } return 0;}
2.function.c
作为补充线程池的函数#include "../include/head.h"#include "../include/threadpool.h"#include "../include/queue.h"#include "../include/mainthread.h"#include "../include/childthread.h"#include "../include/register_login.h"int threadPoolInit(pThreadPool_t pPool,int threadNum){ pPool->threadNum = threadNum; pPool->pthid = (pthread_t *)calloc(threadNum,sizeof(pthread_t)); queueInit(&pPool->Queue); return 0;}int threadPoolStart(pThreadPool_t pPool){ for(int i = 0;i< pPool->threadNum;++i) { pthread_create(&pPool->pthid[i],NULL,threadFunc,&pPool->Queue); } return 0;}void *threadFunc(void *p){ pQue_t pQueue = (pQue_t)p; pNote_t pCur; int getsuccess = 1; while(1) { pthread_mutex_lock(&pQueue->mutex); if(0 == pQueue->size) { pthread_cond_wait(&pQueue->cond,&pQueue->mutex); } getsuccess = queueGet(pQueue,&pCur); pthread_mutex_unlock(&pQueue->mutex); //如果收到的任务中文件描述符为-1,代表进行线程退出流程 if(pCur->clientFd == -1) { pthread_exit(0); } //如果获得任务成功,执行任务 if(0 == getsuccess) { /* Register_Login_Screen(pCur->clientFd); */ transFile(pCur->clientFd); free(pCur); pCur = NULL; } }}int queueInit(pQue_t pQueue){ pQueue->size = 0; pQueue->pHead = NULL; pQueue->pTail = NULL; pthread_mutex_init(&pQueue->mutex,NULL); pthread_cond_init(&pQueue->cond,NULL); return 0;}int queueInsert(pQue_t pQueue,pNote_t pNote){ if(NULL == pQueue->pHead) { pQueue->pHead = pNote; pQueue->pTail = pNote; } else { pQueue->pTail->next = pNote; pQueue->pTail = pNote; } pQueue->size++; return 0;}int queueGet(pQue_t pQueue,pNote_t *pGet){ if(0 == pQueue->size) { return -1; } *pGet = pQueue->pHead; pQueue->pHead = pQueue->pHead->next; pQueue->size--; if(0 == pQueue->size) { pQueue->pTail = NULL; } return 0;}int tcpInit(char *ip,char *port,int *sockfd){ int sfd = socket(AF_INET,SOCK_STREAM,0); ERROR_CHECK(sfd,-1,"socket"); struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = inet_addr(ip); saddr.sin_port = htons(atoi(port)); int ret = bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr)); ERROR_CHECK(ret,-1,"bind"); ret = listen(sfd,10); ERROR_CHECK(ret,-1,"listen"); *sockfd = sfd; return 0;}int epfdAddfd(int fd,int epfd){ struct epoll_event event; memset(&event,0,sizeof(event)); event.events = EPOLLIN; event.data.fd = fd; int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event); ERROR_CHECK(ret,-1,"epoll_add"); return 0;}int transFile(int clientfd){ Train_t train; memset(&train,0,sizeof(train)); int fd = open("file",O_RDWR); //传输文件名 train.len = 4; strcpy(train.buf,"file"); send(clientfd,&train,4+train.len,0); //传输文件长度 struct stat fileInfo; bzero(&fileInfo,sizeof(fileInfo)); fstat(fd,&fileInfo); train.len = sizeof(fileInfo.st_size); memcpy(train.buf,&fileInfo.st_size,train.len); send(clientfd,&train,4+train.len,0); while(1) { int ret = read(fd,train.buf,sizeof(train.buf)); train.len = ret; int ret1 = send(clientfd,&train,4+train.len,0); if(0 == ret) { break; } if(-1 == ret1) { printf("client fault\n"); break; } } return 0;}
3.insert.c
插入客户账号,盐值和密文数据,id自增int mysqlInsert(char *name,char *salt,char* passwd){ if(NULL==name||NULL==salt||NULL==passwd){ //若输入的字符串为空 printf("大兄弟,你传入mysqlInsert的字符串是空的"); return -1; } MYSQL *conn; char *server = "localhost"; char *user = "root"; char *password = "lily_931216asd"; char *database = "clientInfo";//要访问的数据库名称 char query[200]={ 0}; //char query[200]="insert into ZGMF (name, salt, passwd) values ('timo', 'sadad12121', '12312sfqwe1')"; int queryResult; sprintf(query,"insert into clientShadow (nickname,salt,passwd) values ('%s','%s','%s')",name,salt,passwd); conn = mysql_init(NULL); //连接数据库,看连接是否成功,只有成功才能进行后面的操作 if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { printf("Error connecting to database: %s\n", mysql_error(conn)); } else { printf("Connected...\n"); } queryResult = mysql_query(conn, query); if(queryResult) { printf("Error making query:%s\n", mysql_error(conn)); mysql_close(conn); return -1;//表示插入失败 } else { printf("insert success\n"); } mysql_close(conn); return 0;//表示插入成功}
4.getsalt
根据用户名查盐值,把盐值发给sfd的哪一方#include "../include/head.h"#include "../include/register_login.h"//根据用户名查盐值,把盐值发给sfd的哪一方int getSalt(char* nameStr,int sfd){ MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; char *server = "localhost"; char *user = "root"; char *password = "lily_931223asd"; char *database = "clientInfo";//要访问的数据库名称 char query[300] = "select salt from clientShadow where nickname='"; unsigned int queryRet; clientInfo_t clientInfo; sprintf(query, "%s%s%s", query, nameStr, "'"); /* strcpy(query,"select * from hero"); */ //在输出前先打印查询语句 puts(query); //初始化 conn = mysql_init(NULL); if(!conn) { printf("MySQL init failed\n"); return -1; } //连接数据库,看连接是否成功,只有成功才能进行后面的操作 if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { printf("Error connecting to database: %s\n", mysql_error(conn)); return -1; } else { printf("MySQL Connected...\n"); } //把SQL语句传递给MySQL queryRet = mysql_query(conn, query); if(queryRet) { printf("Error making query: %s\n", mysql_error(conn)); } else { //用mysql_num_rows可以得到查询的结果集有几行 //要配合mysql_store_result使用 //第一种判断方式 res = mysql_store_result(conn); printf("mysql_num_rows = %lu\n", (unsigned long)mysql_num_rows(res)); //第二种判断方式,两种方式不能一起使用 /* res = mysql_use_result(conn); */ row = mysql_fetch_row(res); if(NULL == row) { printf("Don't find any data\n"); } else { do { /* printf("num=%d\n",mysql_num_fields(res));//列数 */ //每次for循环打印一整行的内容 for(queryRet = 0; queryRet < mysql_num_fields(res); ++queryRet) { /* printf("%8s ", row[queryRet]); */ char buf[14] = { 0}; sprintf(buf,"%d %s",3,row[queryRet]); send(sfd,buf,strlen(buf),0); /* sscanf(row[queryRet],"%d%s%s%s",&clientInfo.id,clientInfo.nickName,clientInfo.salt,clientInfo.Passwd); */ } /* puts(clientInfo.salt); */ printf("\n"); }while(NULL != (row = mysql_fetch_row(res))); } mysql_free_result(res); } mysql_close(conn); return 0;}
5.queryByName
输入名字,看用户表是否有这个用户,若有返回0//输入名字,打印数据库的名字int queryByName(char* nameStr){ if(NULL==nameStr){ printf("大兄弟,你传给queryByName的字符串是空的呀!\n"); return -1; } MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; char *server = "localhost";//本机 char *user = "root";//登录账户 char *password = "lily_931216asd";//登录密码 char *database = "clientInfo";//要访问的数据库名称 char query[300] = "select * from clientShadow where nickname='";//按名字查找 unsigned int queryRet; clientInfo_t clientInfo; sprintf(query, "%s%s%s", query, nameStr, "'");//拼接成命令字符串 /* strcpy(query,"select * from hero"); */ //在输出前先打印查询语句 puts(query); //初始化数据库 conn = mysql_init(NULL); if(!conn) { printf("MySQL init failed\n"); return -1; } //连接数据库,看连接是否成功,只有成功才能进行后面的操作 if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { //若连接数据库失败 printf("Error connecting to database: %s\n", mysql_error(conn)); return -1; } else//若连接数据库成功 { printf("MySQL Connected...\n"); } //把SQL语句传递给MySQL queryRet = mysql_query(conn, query); if(queryRet)//若传输失败 { printf("Error making query: %s\n", mysql_error(conn)); return -1; } else//若传递命令成功 { //用mysql_num_rows可以得到查询的结果集有几行 //要配合mysql_store_result使用 //第一种判断方式 res = mysql_store_result(conn);//表示查到结果集有几列 printf("mysql_num_rows = %lu\n", (unsigned long)mysql_num_rows(res)); //第二种判断方式,两种方式不能一起使用 /* res = mysql_use_result(conn); */ row = mysql_fetch_row(res); if(NULL == row)//若没读到数据 { printf("Don't find any data\n"); } else//读到数据 { do { /* printf("num=%d\n",mysql_num_fields(res));//列数 */ //每次for循环打印一整行的内容 for(queryRet = 0; queryRet < mysql_num_fields(res); ++queryRet) { //printf("%8s ", row[queryRet]); if(row[queryRet]!=NULL){ printf("find account in database!\n"); break;//找到就退出,否则会打印四行find account } } printf("\n");//换行 }while(NULL != (row = mysql_fetch_row(res))); } mysql_free_result(res); } mysql_close(conn);//关闭mysql服务 return 0;//表示找到}
6.queryByPasswd
根据密文,看是否在数据库中,在就返回0//输入名字,打印数据库的名字int queryByPasswd(char* passWd){ if(NULL==passWd){ printf("大兄弟,你给queryByPasswd的字符串是空的呀!\n"); return -1; } MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; char *server = "localhost";//本机 char *user = "root";//登录账户 char *password = "lily_931223asd";//登录密码 char *database = "clientInfo";//要访问的数据库名称 char query[300] = "select * from clientShadow where passwd='";//按密文查找 unsigned int queryRet; sprintf(query, "%s%s%s", query, passWd, "'");//拼接成命令字符串 /* strcpy(query,"select * from hero"); */ //在输出前先打印查询语句 puts(query); //初始化数据库 conn = mysql_init(NULL); if(!conn) { printf("MySQL init failed\n"); return -1; } //连接数据库,看连接是否成功,只有成功才能进行后面的操作 if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { //若连接数据库失败 printf("Error connecting to database: %s\n", mysql_error(conn)); return -1; } else//若连接数据库成功 { printf("MySQL Connected...\n"); } //把SQL语句传递给MySQL queryRet = mysql_query(conn, query); if(queryRet)//若传输失败 { printf("Error making query: %s\n", mysql_error(conn)); return -1; } else//若传递命令成功 { //用mysql_num_rows可以得到查询的结果集有几行 //要配合mysql_store_result使用 //第一种判断方式 res = mysql_store_result(conn);//表示查到结果集有几列 printf("mysql_num_rows = %lu\n", (unsigned long)mysql_num_rows(res)); //第二种判断方式,两种方式不能一起使用 /* res = mysql_use_result(conn); */ row = mysql_fetch_row(res); if(NULL == row)//若没读到数据 { printf("Don't find any data\n"); return -1;//返回-1表示没找到 } else//读到数据 { do { /* printf("num=%d\n",mysql_num_fields(res));//列数 */ //每次for循环打印一整行的内容 for(queryRet = 0; queryRet < mysql_num_fields(res); ++queryRet) { //printf("%8s ", row[queryRet]); if(row[queryRet]!=NULL){ printf("find account in database!\n"); break;//找到就退出,否则会打印四行find account } } printf("\n");//换行 }while(NULL != (row = mysql_fetch_row(res))); } mysql_free_result(res); } mysql_close(conn);//关闭mysql服务 return 0;//表示找到}
7.Screem.c
生成盐值和用户登录程序#include "../include/head.h"#include "../include/register_login.h"//生成盐值int GenerateStr(char *str){ int i,flag; srand(time(NULL)); for(i = 0;i
转载地址:http://ytno.baihongyu.com/