日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Tcp、select函数实现在线词典(C语言)

發(fā)布時(shí)間:2023/12/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tcp、select函数实现在线词典(C语言) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

功能:
注冊(cè):添加用戶名和密碼到數(shù)據(jù)庫(kù)。
登錄:檢索數(shù)據(jù)庫(kù),查詢是否符合。
查詢:檢索字典文本文件,查詢結(jié)果存入數(shù)據(jù)庫(kù)中。
歷史:檢索數(shù)據(jù)庫(kù),將登錄賬戶的查詢歷史打印。

TCP服務(wù)器:

聲明與定義

#define ERRLOG(msg) \do \{ \printf("%s %s(%d):", __FILE__, __func__, __LINE__); \perror(msg); \exit(-1); \} while (0) //消息結(jié)構(gòu)體封裝 typedef struct msg {char code;char name[20];char txt[128]; } msg_t;sqlite3 *sql_init();//數(shù)據(jù)庫(kù)初始化 int log_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd);//注冊(cè) int select_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd);//登錄 int printf_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd);//檢索單詞 int history_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd);//查看歷史 int str_deal(char *buf);//字符串處理 int time_get(char *timestr);//獲取時(shí)間

主函數(shù)體

//檢查輸入if (3 != argc){printf("Usage: %s <IP> <port>\n", argv[0]);return -1;} 1、第一步配置服務(wù)器結(jié)構(gòu)體和套接字 //套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){ERRLOG("socket error");} //配置服務(wù)器結(jié)構(gòu)體struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));serveraddr.sin_addr.s_addr = inet_addr(argv[1]);socklen_t serveraddr_len = sizeof(serveraddr);if (-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len)){ERRLOG("bind error");}if (-1 == listen(sockfd, 5)){ERRLOG("listen error");} 2、配置select函數(shù)的文件句柄 int maxfd = 0;fd_set readfds;fd_set readfdstemp;FD_ZERO(&readfds);FD_ZERO(&readfdstemp);//將套接字描述符添加到句柄中FD_SET(sockfd, &readfds);maxfd = maxfd > sockfd ? maxfd : sockfd; 3、初始化數(shù)據(jù)庫(kù) sqlite3 *my_sql = sql_init(); 4、通過(guò)select函數(shù)檢索句柄實(shí)現(xiàn)的邏輯結(jié)構(gòu) int ret = 0;//保存有幾個(gè)文件描述符就緒int i = 0;//在循環(huán)中代表了文件描述符int clientfd;//客戶端連接創(chuàng)建的套接字int nbyte = 0;//接受多少字節(jié)while (1){FD_ZERO(&readfdstemp);readfdstemp = readfds;//阻塞等待有1個(gè)或者多個(gè)文件描述符就緒ret = select(maxfd + 1, &readfdstemp, NULL, NULL, NULL);if (ret == -1){PRINT_ERR("select init error");}else{//遍歷句柄,區(qū)分有客戶端連接還是客戶端發(fā)送消息for (i = 3; i < (maxfd + 1) && ret != 0; i++){if (FD_ISSET(i, &readfdstemp)){if (i == sockfd){if ((clientfd = accept(i, NULL, NULL)) == -1){PRINT_ERR("accept error");}printf("新用戶已連接\n");FD_SET(clientfd, &readfds);maxfd = maxfd > clientfd ? maxfd : clientfd;}else{memset(&severmsg, 0, sizeof(severmsg));if ((nbyte = recv(i, &severmsg, sizeof(severmsg), 0)) == -1){PRINT_ERR("recv error");}else if (nbyte == 0){printf("用戶斷開(kāi)連接\n");FD_CLR(i, &readfds);close(i);continue;}//根據(jù)結(jié)構(gòu)體中的操作碼.code判斷客戶端需求switch (severmsg.code){case '1':log_sql(&severmsg, my_sql, i);break;case '2':select_sql(&severmsg, my_sql, i);break;case '3':printf_sql(&severmsg, my_sql, i);break;case '4':history_sql(&severmsg, my_sql, i);break;}}//每次處理完一個(gè)就緒,已就緒的文件描述符就減少了一個(gè)ret--;}}}}

功能模塊
數(shù)據(jù)庫(kù)初始化:

sqlite3 *sql_init() {sqlite3 *my_sql = NULL;int ret = sqlite3_open("dictionary.db", &my_sql);if (ret != SQLITE_OK){printf("error:%d , errstr:%s", ret, sqlite3_errmsg(my_sql));exit(-1);}char *errstr = NULL;char user[128] = "CREATE TABLE IF NOT EXISTS usr (name txt primary key, pass txt);";char hissql[128] = "CREATE TABLE IF NOT EXISTS history (name txt, date txt, word txt,jieshi char);";if ((ret = sqlite3_exec(my_sql, user, NULL, NULL, &errstr)) != SQLITE_OK){printf("errcode:[%d] errstr:[%s]\n", ret, errstr);exit(-1);}if ((ret = sqlite3_exec(my_sql, hissql, NULL, NULL, &errstr)) != SQLITE_OK){printf("errcode:[%d] errstr:[%s]\n", ret, errstr);exit(-1);}sqlite3_free(errstr);return my_sql; } 2、注冊(cè)用戶名 int log_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd) {int ret = 0;char sqlstr[200] = {0};sprintf(sqlstr, "INSERT INTO usr VALUES('%s' , '%s')", clientmsg->name, clientmsg->txt);if ((ret = sqlite3_exec(my_sql, sqlstr, NULL, NULL, NULL)) != SQLITE_OK){printf("errcode:[%d] errstr:[%s]\n", ret, sqlite3_errmsg(my_sql));}if (send(clientfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}return 0; } 3、登錄用戶名和密碼 int select_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd) {int ret = 0;char sqlstr[200] = {0};char **result;int row;int col;sprintf(sqlstr, "SELECT * FROM usr WHERE name='%s' AND pass='%s'", clientmsg->name, clientmsg->txt);if ((ret = sqlite3_get_table(my_sql, sqlstr, &result, &row, &col, NULL)) != SQLITE_OK){printf("errcode:[%d] errstr:[%s]\n", ret, sqlite3_errmsg(my_sql));}if (row == 0){//若無(wú)符合的用戶名和密碼,操作碼置5。告訴客戶端用戶名或密碼錯(cuò)誤clientmsg->code = '5';}sqlite3_free_table(result);if (send(clientfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}printf("%c,%s,%s\n", clientmsg->code, clientmsg->name, clientmsg->txt);return 0; } 4、檢索詞典 int printf_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd) {//打開(kāi)文件FILE *fp;char buf[300] = {0};if ((fp = fopen("dict.txt", "r")) == NULL){PRINT_ERR("open dictionary error");}int flag = 0;while (fgets(buf, sizeof(buf), fp) != NULL){if (strncmp(buf, clientmsg->txt, strlen(clientmsg->txt)) == 0){if (buf[strlen(clientmsg->txt)] == ' '){str_deal(buf);flag = 1;break;}}}if (flag == 1){//處理查詢結(jié)果char word[30] = {0};strcpy(word, clientmsg->txt);char *p = buf + (strlen(clientmsg->txt) + 1);strcpy(clientmsg->txt, p);//獲取時(shí)間char timestr[50] = {0};time_get(timestr);//保存結(jié)果到歷史中int ret = 0;char sqlstr[200] = {0};sprintf(sqlstr, "INSERT INTO history VALUES('%s' ,'%s', '%s','%s')", clientmsg->name, timestr, word, p);if ((ret = sqlite3_exec(my_sql, sqlstr, NULL, NULL, NULL)) != SQLITE_OK){printf("errcode:[%d] errstr:[%s]\n", ret, sqlite3_errmsg(my_sql));}}else{strcpy(clientmsg->txt, "詞庫(kù)中無(wú)此單詞,請(qǐng)檢查");}if (send(clientfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}fclose(fp);return 0; } 5、歷史記錄查詢 int history_sql(msg_t *clientmsg, sqlite3 *my_sql, int clientfd) {int ret = 0;char sqlstr[200] = {0};char **result;int row;int col;sprintf(sqlstr, "SELECT * FROM history WHERE name='%s'", clientmsg->name);if ((ret = sqlite3_get_table(my_sql, sqlstr, &result, &row, &col, NULL)) != SQLITE_OK){printf("errcode:[%d] errstr:[%s]\n", ret, sqlite3_errmsg(my_sql));}//一行發(fā)送一次int i = 0;int j = 0;for (i = 0; i < col; i++);//函數(shù)結(jié)果的數(shù)組中前四個(gè)為表頭int index = i;for (i = 0; i < row; i++){for (j = 0; j < col;){ //結(jié)果:用戶名、時(shí)間、單詞、單詞解釋……//根據(jù)get_table函數(shù)的結(jié)果 +1為時(shí)間、+2為單詞、+3為單詞解釋sprintf(clientmsg->txt, "%s %s : %s", result[index + 1], result[index + 2], result[index+3]);if (send(clientfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}index += 4;j += 4;}}//發(fā)送結(jié)束符strcpy(clientmsg->txt, "**over**");if (send(clientfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}return 0; } 6、字符串處理,刪除多余的空格。每個(gè)空格處,只保留一個(gè)空格 int str_deal(char *buf) {for (int i = 0; buf[i] != '\0';){if (buf[i] == ' ' && buf[i + 1] == ' '){for (int j = i + 1; buf[j] != '\0'; j++){buf[j] = buf[j + 1];}}else{i++;}}return 0; } 7、獲取系統(tǒng)時(shí)間 int time_get(char *timestr) {time_t time_history;struct tm *tm;if ((time_history = time(NULL)) == -1)PRINT_ERR("get time error");if ((tm = localtime(&time_history)) == NULL)PRINT_ERR("change time error");sprintf(timestr, "%d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);return 0; }

客戶端

聲明與定義

#define ERRLOG(msg) \do \{ \printf("%s %s(%d):", __FILE__, __func__, __LINE__); \perror(msg); \exit(-1); \} while (0)typedef struct msg {char code;char name[20];char txt[128]; } msg_t;int log_sql(msg_t *clientmsg, int sockfd); int select_sql(msg_t *clientmsg, int sockfd); int printf_sql(msg_t *clientmsg, int sockfd); int history_sql(msg_t *clientmsg, int sockfd);

主函數(shù)體

if (3 != argc){printf("Usage: %s <IP> <port>\n", argv[0]);return -1;} 1、配置服務(wù)器和服務(wù)器結(jié)構(gòu)體、連接服務(wù)器 int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){ERRLOG("socket error");}struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));serveraddr.sin_addr.s_addr = inet_addr(argv[1]);socklen_t serveraddr_len = sizeof(serveraddr);if (-1 == connect(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len)){ERRLOG("connect error");} 2、邏輯及實(shí)現(xiàn) msg_t clientmsg;memset(&clientmsg, 0, sizeof(clientmsg));while (1){printf("************************************************\n");printf("**************1、注冊(cè) 2、登錄 *******************\n");printf("************************************************\n");scanf(" %c", &(clientmsg.code));printf("請(qǐng)輸入用戶名和密碼:");scanf("%s %s", clientmsg.name, clientmsg.txt);switch (clientmsg.code){case '1':log_sql(&clientmsg, sockfd);break;case '2':select_sql(&clientmsg, sockfd);if (clientmsg.code == '2'){ //如果登陸失敗,服務(wù)器傳回錯(cuò)誤碼5goto NEXT;}break;}memset(clientmsg.txt, 0, sizeof(clientmsg.txt));clientmsg.code = 0;} NEXT:while (1){printf("************************************************\n");printf("**********1、查詢 2、歷史 3、登出***************\n");printf("************************************************\n");scanf(" %c", &(clientmsg.code));switch (clientmsg.code){case '1':clientmsg.code = '3';printf("輸入單詞:");scanf("%s", clientmsg.txt);printf_sql(&clientmsg, sockfd);break;case '2':clientmsg.code = '4';history_sql(&clientmsg, sockfd);break;}memset(clientmsg.txt, 0, sizeof(clientmsg.txt));clientmsg.code = 0;}

功能模塊

1、注冊(cè)模塊 int log_sql(msg_t *clientmsg, int sockfd) {int nbyte = 0;if (send(sockfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}if ((nbyte = recv(sockfd, clientmsg, sizeof(msg_t), 0)) == -1){PRINT_ERR("recv error");}if (clientmsg->code == '5'){printf("注冊(cè)成功\n");}else{printf("用戶名已被注冊(cè)\n");}return 0; } 2、登錄 int select_sql(msg_t *clientmsg, int sockfd) {int nbyte = 0;if (send(sockfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}if ((nbyte = recv(sockfd, clientmsg, sizeof(msg_t), 0)) == -1){PRINT_ERR("recv error");}if (clientmsg->code == '5'){printf("用戶名或密碼不正確,請(qǐng)確認(rèn)用戶名和密碼或注冊(cè)\n");}else{printf("登錄成功\n");}return 0; } 3、查詢 int printf_sql(msg_t *clientmsg, int sockfd) {int nbyte = 0;if (send(sockfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}if ((nbyte = recv(sockfd, clientmsg, sizeof(msg_t), 0)) == -1){PRINT_ERR("recv error");}printf("%s\n", clientmsg->txt);return 0; } 4、歷史查看 int history_sql(msg_t *clientmsg, int sockfd) {int nbyte = 0;if (send(sockfd, clientmsg, sizeof(msg_t), 0) == -1){PRINT_ERR("send error");}//判斷是否接收完畢while (strcmp(clientmsg->txt,"**over**")){if ((nbyte = recv(sockfd, clientmsg, sizeof(msg_t), 0)) == -1){PRINT_ERR("recv error");}printf("%s\n", clientmsg->txt);}return 0; }

總結(jié)

以上是生活随笔為你收集整理的Tcp、select函数实现在线词典(C语言)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。