• 电子词典项目


    目录

    目录

    头文件:dict.h:

    源文件:dict.c:

    服务器测试文件:serDict.c:

    客户端测试文件:cliDict.c:


    头文件:dict.h:
    1. #ifndef __DICT_H__
    2. #define __DICT_H__
    3. #include
    4. #include
    5. #define SERIP "192.168.114.73"
    6. #define PORT 8888
    7. #define ERR_MSG(msg) do{\
    8. printf("%d: ",__LINE__);\
    9. perror(msg);\
    10. }while(0);
    11. /*服务器使用 */
    12. //词典数据库的初始化和导入
    13. int dict_init(sqlite3 *db);
    14. //TCP服务器搭建函数
    15. int TCP_ser_set(struct sockaddr_in* psin);
    16. //回收子进程函数
    17. void handler(int signum);
    18. //子进程中的操作
    19. void child_operate(int newfd, sqlite3 *db);
    20. /*服务器使用 */
    21. /*客户端使用 */
    22. //TCP客户端搭建函数
    23. int TCP_cli_set();
    24. //客户端中的操作
    25. void cli_operate(int cfd);
    26. /*客户端使用 */
    27. #endif
    源文件:dict.c:
    1. #include
    2. #include
    3. #include "dict.h"
    4. int do_create(sqlite3 *db);
    5. int do_insert(sqlite3 *db, char * English, char *Chinese);
    6. int msg_get(FILE *fp, char*pEng, char *pChin);
    7. int do_init(sqlite3 *db);
    8. int usrname_not_reuse(sqlite3 *db, const char *usrname, const char *tablename);
    9. int dict_init(sqlite3 *db)
    10. {
    11. //初始化数据库中词典数据表
    12. do_init(db);
    13. printf("数据库初始化成功\n");
    14. //打开文件
    15. FILE *fp;
    16. char English[32] = "";
    17. char Chinese[64] = "";
    18. if(NULL == (fp=fopen("./dict.txt","r"))){
    19. printf("%d:",__LINE__);
    20. perror("fopen error");
    21. return -1;
    22. }
    23. //创建表格
    24. do_create(db);
    25. printf("词典数据导入中\n...\n");
    26. while(1){
    27. //从dict.txt中读取一行的数据
    28. bzero(English, sizeof(English));
    29. bzero(Chinese, sizeof(Chinese));
    30. msg_get(fp, English, Chinese);
    31. //将English和Chinese写入表格中
    32. do_insert(db, English, Chinese);
    33. //printf("%s\t%s\n",English, Chinese);
    34. if(feof(fp)){
    35. printf("导入成功\n");
    36. break;
    37. }
    38. }
    39. //关闭文件
    40. fclose(fp);
    41. return 0;
    42. }
    43. int msg_get(FILE *fp, char* pEng, char *pChin){
    44. char tmp = 0;
    45. int i = 0;
    46. while((tmp = fgetc(fp))!=' '){
    47. pEng[i] = tmp;
    48. i++;
    49. if(feof(fp)){
    50. return 0;
    51. }
    52. }
    53. i = 0;
    54. while(fgetc(fp)==' ');
    55. fseek(fp,-1,SEEK_CUR);
    56. while((tmp = fgetc(fp))!='\n'){
    57. pChin[i] = tmp;
    58. i++;
    59. if(feof(fp)){
    60. pChin[i-1] = 0;
    61. break;
    62. }
    63. }
    64. return 0;
    65. }
    66. int do_create(sqlite3 *db){
    67. if(db == NULL){
    68. printf("数据库不存在\n");
    69. return -1;
    70. }
    71. //创建词典数据表
    72. char sql[128] = "create table if not exists dict(ENGLISH char, TRANSLATION char);";
    73. char *errmsg = NULL;
    74. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    75. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    76. return -1;
    77. }
    78. //创建已注册用户数据表
    79. bzero(sql,sizeof(sql));
    80. strcpy(sql,"create table if not exists registeredUsr(id char primary key, passwd char);");
    81. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    82. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    83. return -1;
    84. }
    85. //创建已登录用户数据表
    86. bzero(sql,sizeof(sql));
    87. strcpy(sql,"create table if not exists loadedUsr(id char primary key, passwd char);");
    88. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    89. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    90. return -1;
    91. }
    92. //创建成功
    93. return 0;
    94. }
    95. int do_init(sqlite3 *db){
    96. if(db == NULL){
    97. printf("数据库不存在\n");
    98. return -1;
    99. }
    100. char sql[128] = "drop table dict;";
    101. char *errmsg = NULL;
    102. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    103. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    104. return -1;
    105. }
    106. //创建成功
    107. return 0;
    108. }
    109. //插入表格函数
    110. int do_insert(sqlite3 *db, char * English, char *Chinese){
    111. if(db == NULL){
    112. printf("数据库不存在\n");
    113. return -1;
    114. }
    115. char sql[128] = "";
    116. snprintf(sql, sizeof(sql),"insert into dict values(\"%s\", \"%s\");",English, Chinese);
    117. char *errmsg = NULL;
    118. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    119. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    120. return -1;
    121. }
    122. return 0;
    123. }
    124. //TCP服务器搭建函数
    125. int TCP_ser_set(struct sockaddr_in* psin){
    126. int sfd;
    127. if((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    128. ERR_MSG("socket error");
    129. return -1;
    130. }
    131. int optval = 1;
    132. //允许端口快速复用
    133. if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0){
    134. ERR_MSG("setsockopt error");
    135. return -1;
    136. }
    137. //获取地址信息结构体
    138. struct sockaddr_in sin;
    139. sin.sin_family = AF_INET;
    140. sin.sin_port = htons(PORT);
    141. sin.sin_addr.s_addr = inet_addr(SERIP);
    142. * psin = sin;
    143. //绑定
    144. if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))<0){
    145. ERR_MSG("bind error");
    146. return -1;
    147. }
    148. //设为监听
    149. if(listen(sfd,128)<0){
    150. ERR_MSG("listen error");
    151. return -1;
    152. }
    153. printf("服务器搭建成功\n");
    154. return sfd;
    155. }
    156. //回收子进程函数
    157. void handler(int signum){
    158. while(waitpid(-1,NULL,WNOHANG)!=0);
    159. }
    160. //子进程中的操作
    161. void child_operate(int newfd, sqlite3 *db){
    162. //判断传入的newfd是否合法
    163. if(newfd<0){
    164. printf("连接失败\n");
    165. return;
    166. }
    167. char buf[150] = " ";
    168. //用于读取数据包中的操作码
    169. unsigned short *operatorPtr = (unsigned short*)buf;
    170. //用于登录后记录用户名,便于读写对应用户的历史记录数据库
    171. char usrname[20] = " ";
    172. //用于读取数据包中的用户名
    173. char *usrnamePtr = buf + 2;
    174. //需要后续计算得到数据包中数据的位置
    175. char *dataPtr = NULL;
    176. //获取用户名的长度
    177. int usrnameLen = 0;
    178. //定义一个变量接收返回值
    179. int res = 0;
    180. //保存命令的数组
    181. char sql[128] = " ";
    182. while(1){
    183. bzero(buf,sizeof(buf));
    184. //接收
    185. if(recv(newfd, buf, sizeof(buf), 0) == -1){
    186. ERR_MSG("recv error");
    187. break;
    188. }
    189. //获取的是用户名的长度
    190. usrnameLen = strlen(usrnamePtr);
    191. //可知数据包中数据的位置为
    192. dataPtr = usrnamePtr + usrnameLen + 1;
    193. //printf("%s\n",buf);
    194. //send(newfd,buf,sizeof(buf),0);
    195. //注册
    196. if(1 == *operatorPtr){
    197. //现在,usrnamePtr指向用户名,dataPtr是数据的起头,在注册里面,数据包应该保存用户对应的密码
    198. //检索已注册用户数据表,看看用户名是否存在
    199. res = usrname_not_reuse(db, usrnamePtr, "registeredUsr");
    200. if(-1 == res){
    201. //说明这个函数调用遇到问题
    202. //组一个返回包
    203. *operatorPtr = 7;
    204. strcpy(dataPtr,"there is something wrong");
    205. }else if(0 == res){
    206. //说明用户名已存在
    207. *operatorPtr = 7;
    208. strcpy(dataPtr,"用户名已存在");
    209. }else if(1 == res){
    210. //说明用户名不在数据库中,可以进行注册
    211. bzero(sql, sizeof(sql));
    212. snprintf(sql, sizeof(sql),"insert into registeredUsr values(\"%s\", \"%s\");",usrnamePtr, dataPtr);
    213. char *errmsg = NULL;
    214. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    215. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    216. break;
    217. }
    218. *operatorPtr = 7;
    219. strcpy(dataPtr,"注册成功");
    220. }
    221. }else if(2 == *operatorPtr){
    222. //登录
    223. //现在,usrnamePtr指向用户名,dataPtr是数据的起头,在登录里面,数据包应该保存用户对应的密码
    224. //检索已登录用户数据表,看看用户名是否存在
    225. res = usrname_not_reuse(db, usrnamePtr, "registeredUsr");
    226. if(-1 == res){
    227. //说明这个函数调用遇到问题
    228. //组一个返回包
    229. *operatorPtr = 7;
    230. strcpy(dataPtr,"there is something wrong");
    231. }else if(1 == res){
    232. //说明在已注册表中未找到该用户,说明该账号还没被注册
    233. *operatorPtr = 7;
    234. strcpy(dataPtr,"该账号还未被注册,请先注册");
    235. }else if(0 == res){
    236. //说明在已注册表中找到了该用户,进行下一步登录操作
    237. res = usrname_not_reuse(db, usrnamePtr, "loadedUsr");
    238. if(-1 == res){
    239. //说明这个函数调用遇到问题
    240. //组一个返回包
    241. *operatorPtr = 7;
    242. strcpy(dataPtr,"there is something wrong");
    243. }else if(0 == res){
    244. //说明用户名已存在已登录数据表,说明用户已经登录
    245. *operatorPtr = 7;
    246. strcpy(dataPtr,"该账号已登录,请检查账号是否被盗用");
    247. }else if(1 == res){
    248. //说明该用户已注册且未登录,可以进行登录
    249. bzero(sql, sizeof(sql));
    250. char **result = NULL;
    251. int row = 0;
    252. int col = 0;
    253. char *errmsg = NULL;
    254. int flag = 0;
    255. snprintf(sql,sizeof(sql),"select id,passwd from registeredUsr;");
    256. if((res = sqlite3_get_table(db, sql, &result, &row, &col, &errmsg))!=0){
    257. printf("%d:sqlite3_get_table error\n",__LINE__);
    258. printf("%s\n",strerror(res));
    259. break;
    260. }
    261. //遍历比较,第0行是项的名,所以从第一行开始
    262. for(int i=col; i<=row*col; i+=col){
    263. if(strcmp(*(result+i),usrnamePtr) == 0&&strcmp(*(result+i+1),dataPtr) == 0){
    264. //登录成功后要将用户数据写入已登录用户数据表
    265. bzero(sql, sizeof(sql));
    266. snprintf(sql, sizeof(sql),"insert into loadedUsr values(\"%s\", \"%s\");",usrnamePtr, dataPtr);
    267. char *errmsg = NULL;
    268. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    269. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    270. break;
    271. }
    272. //满足条件说明用户密码匹配成功,即登录成功
    273. *operatorPtr = 7;
    274. strcpy(dataPtr,"登录成功");
    275. //将登录成功的用户名保存
    276. strcpy(usrname,usrnamePtr);
    277. flag = 0;
    278. //然后应该新建一个对应用户的历史记录数据表
    279. bzero(sql, sizeof(sql));
    280. snprintf(sql, sizeof(sql),"create table if not exists %shis(ENGLISH char , TRANSLATION char, current timestamp default current_timestamp);",usrname);
    281. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    282. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    283. break;
    284. }
    285. break;
    286. }else{
    287. flag = 1;
    288. }
    289. }
    290. if(1 == flag){
    291. *operatorPtr = 7;
    292. strcpy(dataPtr,"密码错误");
    293. }
    294. }
    295. }
    296. }else if(3 == *operatorPtr){
    297. //退出
    298. //先判断该进程中usrname字符串内是否有内容,如果有的话,说明用户是异常退出,先帮用户
    299. //退出登录,再进行退出操作
    300. if(usrname[0]!=0){
    301. //usrname字符串的第一个元素不为0,说明非空,检查usrname字符串内容是否在
    302. //已登录用户信息数据表中
    303. res = usrname_not_reuse(db, usrname, "loadedUsr");
    304. if(0 == res){
    305. //说明用户还在已登录用户信息表中,说明用户确实是异常退出,先退出登录
    306. //从已登录用户数据表中,将用户名对应的项删除
    307. bzero(sql, sizeof(sql));
    308. char *errmsg = NULL;
    309. snprintf(sql,sizeof(sql),"delete from loadedUsr where id=\'%s\';",usrname);
    310. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    311. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    312. break;
    313. }
    314. //将usrname这个字符串清空
    315. bzero(usrname,sizeof(usrname));
    316. }else if(1 == res){
    317. //说明用户已经退出登录
    318. bzero(usrname,sizeof(usrname));
    319. }
    320. }
    321. //结束函数
    322. return;
    323. }else if(4 == *operatorPtr){
    324. //查询
    325. //接收到要查询的英文单词,需要在dict数据表中查找,没找到的话也应该返回一个数据提示
    326. bzero(sql, sizeof(sql));
    327. char **result = NULL;
    328. int row = 0;
    329. int col = 0;
    330. char *errmsg = NULL;
    331. int flag = 0;
    332. snprintf(sql,sizeof(sql),"select ENGLISH,TRANSLATION from dict where ENGLISH=\'%s\';",dataPtr);
    333. if((res = sqlite3_get_table(db, sql, &result, &row, &col, &errmsg))!=0){
    334. printf("%d:sqlite3_get_table error\n",__LINE__);
    335. printf("%s\n",strerror(res));
    336. break;
    337. }
    338. *operatorPtr = 7;
    339. if(strcmp(*(result+2),dataPtr)==0){
    340. //如果查找到的因为原型与发送来的相同,说明要找的单词存在
    341. snprintf(dataPtr,128,"%s\t%s",*(result+2),*(result+3));
    342. //将对应的英文及其翻译还有当时时间记录
    343. bzero(sql, sizeof(sql));
    344. snprintf(sql, sizeof(sql),"insert into %shis values(\"%s\", \"%s\",CURRENT_TIMESTAMP);",usrname, *(result+2), *(result+3));
    345. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    346. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    347. break;
    348. }
    349. }else{
    350. //否则不存在,发送一个反馈的包
    351. strcpy(dataPtr,"抱歉该单词还未收录");
    352. }
    353. }else if(5 == *operatorPtr){
    354. //历史记录
    355. bzero(sql, sizeof(sql));
    356. char **result = NULL;
    357. int row = 0;
    358. int col = 0;
    359. char *errmsg = NULL;
    360. int flag = 0;
    361. bzero(sql, sizeof(sql));
    362. snprintf(sql,sizeof(sql),"select * from %shis;",usrname);
    363. //printf("%s\n",sql);
    364. if((res = sqlite3_get_table(db, sql, &result, &row, &col, &errmsg))!=0){
    365. printf("%d:sqlite3_get_table error\n",__LINE__);
    366. printf("%s\n",strerror(res));
    367. break;
    368. }
    369. *operatorPtr = 7;
    370. for(int i=col; i<=row*col; i+=col){
    371. *operatorPtr = 7;
    372. snprintf(dataPtr,128,"%s\t%s\t%s",*(result+i),*(result+i+1),*(result+i+2));
    373. //发送返回的数据包
    374. send(newfd, buf, sizeof(buf), 0);
    375. bzero(dataPtr,128);
    376. }
    377. }else if(6 == *operatorPtr){
    378. //退出登录
    379. //从已登录用户数据表中,将用户名对应的项删除
    380. bzero(sql, sizeof(sql));
    381. char *errmsg = NULL;
    382. snprintf(sql,sizeof(sql),"delete from loadedUsr where id=\'%s\';",usrname);
    383. if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){
    384. printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));
    385. break;
    386. }
    387. //将usrname这个字符串清空
    388. bzero(usrname,sizeof(usrname));
    389. *operatorPtr = 7;
    390. strcpy(dataPtr,"账号成功退出登录");
    391. }else{
    392. }
    393. //发送返回的数据包
    394. send(newfd, buf, sizeof(buf), 0);
    395. }
    396. }
    397. //查询用户名是否重复函数
    398. int usrname_not_reuse(sqlite3 *db, const char *usrname, const char *tablename){
    399. char **res = NULL;
    400. int row = 0;
    401. int col = 0;
    402. char *errmsg = NULL;
    403. //调用查询函数
    404. char sql[128] = " ";
    405. snprintf(sql,sizeof(sql),"select id from %s;",tablename);
    406. if(sqlite3_get_table(db, sql, &res, &row, &col, &errmsg)!=0){
    407. printf("%d:sqlite3_get_table error\n",__LINE__);
    408. return -1;
    409. }
    410. //遍历比较,第0行是项的名,所以从1开始
    411. for(int i=1; i<=row; i++){
    412. if(strcmp(*(res+i),usrname) == 0){
    413. //满足条件说明用户名已存在,返回0
    414. return 0;
    415. }
    416. }
    417. //遍历到结束,说明该用户名还未存在,返回1
    418. return 1;
    419. }
    420. //TCP客户端搭建函数
    421. int TCP_cli_set(){
    422. int cfd;
    423. if((cfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    424. ERR_MSG("socket error");
    425. return -1;
    426. }
    427. int optval = 1;
    428. //允许端口快速复用
    429. if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0){
    430. ERR_MSG("setsockopt error");
    431. return -1;
    432. }
    433. //获取地址信息结构体
    434. struct sockaddr_in sin;
    435. sin.sin_family = AF_INET;
    436. sin.sin_port = htons(PORT);
    437. sin.sin_addr.s_addr = inet_addr(SERIP);
    438. //连接
    439. if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin))<0){
    440. ERR_MSG("connect error");
    441. return -1;
    442. }
    443. printf("客户端搭建成功\n");
    444. return cfd;
    445. }
    446. //客户端中的操作
    447. void cli_operate(int cfd){
    448. if(cfd<0){
    449. printf("文件描述符有误\n");
    450. return;
    451. }
    452. //菜单
    453. int opt = 0;
    454. char buf[150] = " ";
    455. unsigned short *operatorPtr = (unsigned short *)buf;
    456. //记录用户名
    457. char id[20] = " ";
    458. //记录用户名长度
    459. int idlen = 0;
    460. //记录已登录用户的用户名
    461. char loadedid[20] = " ";
    462. int loadedidlen = 0;
    463. //记录密码
    464. char passwd[20] = " ";
    465. //记录密码长度
    466. int passwdlen = 0;
    467. while(1){
    468. bzero(buf,sizeof(buf));
    469. bzero(id,sizeof(id));
    470. bzero(passwd,sizeof(passwd));
    471. system("clear");
    472. printf("****************************\n");
    473. printf("**********电子词典**********\n");
    474. printf("***********1.注册***********\n");
    475. printf("***********2.登录***********\n");
    476. printf("***********3.退出***********\n");
    477. printf("****************************\n");
    478. printf("请输入>>");
    479. scanf("%d",&opt);
    480. if(1 == opt){
    481. //注册
    482. *operatorPtr = 1;
    483. printf("请输入要注册的用户名:");
    484. while(1){
    485. scanf("%s",id);
    486. while(getchar()!=10);
    487. //记录账号长度,保证长度符合要求才能跳出循环
    488. idlen = strlen(id);
    489. if(idlen>0&&idlen<20){
    490. break;
    491. }
    492. printf("账号长度请不要超过20,请重新输入:");
    493. }
    494. printf("请输入密码:");
    495. while(1){
    496. scanf("%s",passwd);
    497. while(getchar()!=10);
    498. //记录密码长度,保证长度符合要求才能跳出循环
    499. passwdlen = strlen(passwd);
    500. if(passwdlen<20&&passwdlen>0){
    501. break;
    502. }
    503. printf("密码长度请不要超过20,请重新输入:");
    504. }
    505. //将账号写到对应位置
    506. strcpy(buf+2,id);
    507. //将密码写到对应位置
    508. strcpy(buf+3+idlen,passwd);
    509. send(cfd, buf, sizeof(buf), 0);
    510. recv(cfd, buf, sizeof(buf), 0);
    511. printf("%s\n",buf+3+idlen);
    512. }else if(2 == opt){
    513. //登录
    514. *operatorPtr = 2;
    515. printf("请输入要登录的用户名:");
    516. while(1){
    517. scanf("%s",id);
    518. while(getchar()!=10);
    519. //记录账号长度,保证长度符合要求才能跳出循环
    520. idlen = strlen(id);
    521. if(idlen>0&&idlen<20){
    522. break;
    523. }
    524. printf("账号长度请不要超过20,请重新输入:");
    525. }
    526. printf("请输入密码:");
    527. while(1){
    528. scanf("%s",passwd);
    529. while(getchar()!=10);
    530. //记录密码长度,保证长度符合要求才能跳出循环
    531. passwdlen = strlen(passwd);
    532. if(passwdlen<20&&passwdlen>0){
    533. break;
    534. }
    535. printf("密码长度请不要超过20,请重新输入:");
    536. }
    537. //将账号写到对应位置
    538. strcpy(buf+2,id);
    539. //将密码写到对应位置
    540. strcpy(buf+3+idlen,passwd);
    541. send(cfd, buf, sizeof(buf), 0);
    542. recv(cfd, buf, sizeof(buf), 0);
    543. printf("%s\n",buf+3+idlen);
    544. if(strcmp(buf+3+idlen,"登录成功")==0){
    545. strcpy(loadedid,id);
    546. loadedidlen = idlen;
    547. //将账号写到对应位置
    548. strcpy(buf+2,loadedid);
    549. printf("输入任意字符刷新>>");
    550. getchar();
    551. while(getchar()!=10);
    552. while(1){
    553. strcpy(buf+2,loadedid);
    554. system("clear");
    555. printf("****************************\n");
    556. printf("**********电子词典**********\n");
    557. printf("*****usr:%s*****\n",loadedid);
    558. printf("***********1.查询***********\n");
    559. printf("*********2.历史记录*********\n");
    560. printf("*********3.退出登录*********\n");
    561. printf("****************************\n");
    562. printf("请输入>>");
    563. scanf("%d",&opt);
    564. if(1 == opt){
    565. //查找
    566. *operatorPtr = 4;
    567. printf("请输入要查找的单词>>");
    568. scanf("%s",buf+3+loadedidlen);
    569. send(cfd, buf, sizeof(buf), 0);
    570. recv(cfd, buf, sizeof(buf), 0);
    571. printf("%s\n",buf+3+loadedidlen);
    572. }else if(2 == opt){
    573. //历史记录
    574. *operatorPtr = 5;
    575. //由于已经将用户id写入buf包中,只需将包发送即可
    576. send(cfd, buf, sizeof(buf), 0);
    577. recv(cfd, buf, sizeof(buf), 0);
    578. char *dataPtr = buf+3+loadedidlen;
    579. //应该循环接收,那么服务器发包应该在数据区写入结束标志
    580. while(*dataPtr){
    581. printf("%s\n",dataPtr);
    582. recv(cfd, buf, sizeof(buf), 0);
    583. }
    584. }else if(3 == opt){
    585. //退出登录
    586. //发送一个操作码为6的空包,向服务器提示该账号要退出登录
    587. //将记录已登录id的字符串清空,用于存储下一个登录用户id
    588. *operatorPtr = 6;
    589. send(cfd, buf, sizeof(buf), 0);
    590. recv(cfd, buf, sizeof(buf), 0);
    591. printf("%s\n",buf+3+loadedidlen);
    592. bzero(loadedid,sizeof(loadedid));
    593. loadedidlen = 0;
    594. break;
    595. }else{
    596. printf("输入不规范,亲人两行泪,请重新输入\n");
    597. }
    598. printf("输入任意字符刷新>>");
    599. getchar();
    600. while(getchar()!=10);
    601. bzero(buf,sizeof(buf));
    602. }
    603. }
    604. }else if(3 == opt){
    605. //退出
    606. //发送一个操作码为3的空包
    607. *operatorPtr = 3;
    608. send(cfd, buf, sizeof(buf), 0);
    609. break;
    610. }else{
    611. printf("输入不规范,亲人两行泪,请重新输入\n");
    612. }
    613. printf("输入任意字符刷新>>");
    614. getchar();
    615. while(getchar()!=10);
    616. }
    617. }
    服务器测试文件:serDict.c:
    1. #include
    2. #include
    3. #include "dict.h"
    4. int main(int argc, const char *argv[])
    5. {
    6. //回收子进程
    7. signal(SIGCHLD,handler);
    8. //打开数据库
    9. sqlite3 * db;
    10. if(sqlite3_open("./dict.db", &db) != SQLITE_OK){
    11. printf("%d:sqlite3_open error %s\n",__LINE__, sqlite3_errmsg(db));
    12. return -1;
    13. }
    14. //初始化数据库,完成词典数据表的重载以及用户信息数据库的导入
    15. dict_init(db);
    16. struct sockaddr_in sin;
    17. socklen_t addrlen = sizeof(sin);
    18. int sfd;
    19. if((sfd = TCP_ser_set(&sin))<0){
    20. printf("服务器搭建失败");
    21. return -1;
    22. }
    23. pid_t pid;
    24. int newfd;
    25. while(1){
    26. if((newfd = accept(sfd, (struct sockaddr*)&sin, &addrlen))<0){
    27. ERR_MSG("accept error");
    28. return 0;
    29. }
    30. pid = fork();
    31. if(pid == 0){
    32. close(sfd);
    33. printf("这是子进程\n");
    34. child_operate(newfd, db);
    35. close(newfd);
    36. //关闭数据库
    37. if(sqlite3_close(db) != SQLITE_OK){
    38. printf("%d:sqlite3_close error %s\n",__LINE__, sqlite3_errmsg(db));
    39. return -1;
    40. }
    41. exit(EXIT_SUCCESS);
    42. }
    43. close(newfd);
    44. }
    45. //关闭数据库
    46. if(sqlite3_close(db) != SQLITE_OK){
    47. printf("%d:sqlite3_close error %s\n",__LINE__, sqlite3_errmsg(db));
    48. return -1;
    49. }
    50. close(sfd);
    51. return 0;
    52. }
    客户端测试文件:cliDict.c:
    1. #include
    2. #include
    3. #include "dict.h"
    4. int cfd;
    5. //用户按下ctrl+c后给服务器发一个退出登录的包
    6. void handlerINT(int signum){
    7. char buf[150] = " ";
    8. unsigned short *operatorPtr = (unsigned short*)buf;
    9. //发送一个操作码为3的空包,向服务器提示该账号要退出,退出功能中包含了退出登录
    10. *operatorPtr = 3;
    11. send(cfd, buf, sizeof(buf), 0);
    12. }
    13. int main(int argc, const char *argv[])
    14. {
    15. //用户按下ctrl+c后给服务器发一个退出登录的包
    16. signal(2,handlerINT);
    17. //调用TCP客户端搭建函数
    18. if((cfd = TCP_cli_set())<0){
    19. printf("客户端搭建失败\n");
    20. }
    21. cli_operate(cfd);
    22. close(cfd);
    23. return 0;
    24. }

  • 相关阅读:
    【数据结构之栈、队列、数组】
    [CM311-1A]-查看安卓的分区存储情况
    npm install 报错 chromedriver 安装失败的解决办法
    Map和Set的详解
    【1++的数据结构】之哈希(一)
    分享图片或链接到抖音
    300万数据导入导出优化方案,从80s优化到8s(实测)
    2个器件,做1个恒流源
    详解JS遍历对象的五种方法
    Elasticsearch(macbook搭建,Elasticsearch+kibana)一步到位
  • 原文地址:https://blog.csdn.net/sy311SB/article/details/132916283