当前位置:   article > 正文

Ubuntu环境下基于Socket通信的网络聊天系统_socked 聊天室账号密码登录

socked 聊天室账号密码登录

在Linux环境下,利用Socket通信实现网络聊天程序,主要包括以下功能:

(1)系统各菜单功能界面、聊天界面的显示

(2)用户的注册、登录(手机号注册,合格性检测,重复性检测),注册后创建用户文件夹

(3)可支持好友管理(好友列表在线显示、增删查,网络传输文件),账户管理(修改信息,权限变更(创新可调用MD5库文件)

(3)聊天方式分群聊和私聊两种方式,群聊可管理员设置禁言,代码实现禁言单用户,全员禁言代码类同(创新可加入自然语言检测,实现敏感词监督)

(4)保存聊天记录,代码实现保存私聊记录,群聊记录保存类同

(5)实现客户端之间网络传输文件

服务器每接上一个客户端,启动一个线程;

客户端创建收发线程与服务器交互。

Server.c

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <pthread.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <fcntl.h>
  8. #include <string.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <ctype.h>
  12. #include <memory.h>
  13. #include <netinet/ip.h>
  14. #include <netinet/tcp.h>
  15. #include <time.h>
  16. #include <malloc.h>
  17. #include <sys/stat.h>
  18. #include <termios.h>
  19. #define NUM 1024
  20. #define SIZE sizeof(cliMesg) //结构体cliMesg的大小
  21. typedef long long ll;
  22. //账户类
  23. typedef struct client_message
  24. {
  25. char id[20]; //每个账号唯一id, 手机号
  26. char passwd[20]; //账号密码
  27. char name[50]; //账号昵称
  28. char hy[100][20]; //好友列表,最大100个
  29. int hys; //好友数量
  30. int online; //0不在线, 1在线
  31. int fd; //存放客户端成功连接后accept产生的新的套接字, 不在线为-5
  32. int chatroom; //存放是否打开了双人聊天室,打开为1 , 没打开为0
  33. int admin; //管理员权限 -1禁言 - 踢出不能再进
  34. //bMesg status; //禁言
  35. long ed_time;
  36. struct client_message *next; //下一条链表的首地址
  37. }cliMesg;
  38. //信息类
  39. typedef struct friend_message
  40. {
  41. char rid[20]; //收信息的人
  42. char sid[20]; //发信息的人
  43. int type; //信息类型 , 好友请求1 , 私聊信息 2 , 好友请求回复信息3 , 文件传输4 , 文件回复5
  44. char mesg[1024]; //信息
  45. char fname[1024]; //文件名
  46. struct friend_message * next;//下一条信息的首地址
  47. }friMesg;
  48. cliMesg *head=NULL;
  49. friMesg *head1=NULL;
  50. int count =0; //账号数量
  51. int urev_count=0; //未发送的信息
  52. //创建账号信息的头指针
  53. cliMesg *create_count()
  54. {
  55. cliMesg *p1;
  56. p1=(cliMesg *)malloc(SIZE);
  57. if(p1==NULL)
  58. {
  59. printf("create error\n");
  60. return NULL;
  61. }
  62. p1->next=NULL;
  63. //记录账户
  64. FILE *fp;
  65. fp=fopen("counterMsg","a+"); //打开文件
  66. if(fp==NULL)
  67. {
  68. printf("open error\n");
  69. return NULL;
  70. }
  71. //文件为空
  72. if(fgetc(fp)==EOF)
  73. {
  74. fclose(fp);
  75. return p1;
  76. }
  77. //文件有内容
  78. rewind(fp); //文件指针重返文件头
  79. //获取账号数量
  80. int counter_num;
  81. fread(&counter_num,sizeof(int),1,fp);
  82. printf("counter_num=%d\n",counter_num);
  83. count=counter_num;
  84. //建立好友链表
  85. cliMesg t;
  86. cliMesg *tmp,*p;
  87. int i;
  88. for(i=0;i<counter_num;i++)
  89. {
  90. fread(&t,sizeof(cliMesg),1,fp);
  91. p=p1;
  92. while(p->next)
  93. {
  94. p=p->next;
  95. }
  96. tmp=(cliMesg *)malloc(sizeof(cliMesg));
  97. tmp->next=NULL;
  98. strcpy(tmp->id,t.id);
  99. strcpy(tmp->name,t.name);
  100. strcpy(tmp->passwd,t.passwd);
  101. tmp->admin=t.admin;
  102. tmp->hys=t.hys;
  103. tmp->ed_time=t.ed_time;
  104. //有好友将数据存入好友链表
  105. int j;
  106. for(j=0;j<tmp->hys;j++)
  107. {
  108. strcpy(tmp->hy[j],t.hy[j]);
  109. }
  110. tmp->fd= -5; //初始未登录
  111. tmp->chatroom=0; //初始未私聊
  112. tmp->online=0; //初始未在线
  113. //tmp->admin=0; //初始为普通用户
  114. p->next=tmp;
  115. }
  116. fclose(fp);
  117. return p1;
  118. }
  119. //创建未查看信息的头指针
  120. friMesg *create_buffmsg()
  121. {
  122. friMesg *x;
  123. x=(friMesg *)malloc(sizeof(friMesg));
  124. if(x==NULL)
  125. {
  126. printf("create error\n");
  127. return NULL;
  128. }
  129. x->next=NULL;
  130. FILE *fp;
  131. fp=fopen("buffMsg","a+");
  132. if(fp==NULL)
  133. {
  134. printf("open error\n");
  135. return NULL;
  136. }
  137. //如果为空文件关闭文件直接返回头指针
  138. if(fgetc(fp)==EOF)
  139. {
  140. fclose(fp);
  141. return x;
  142. }
  143. rewind(fp);
  144. int n;
  145. fread(&n,sizeof(int),1,fp);
  146. printf("urev_num=%d\n",n);
  147. urev_count=n;
  148. friMesg t;
  149. friMesg *p,*p1;
  150. //创建未查看信息链表
  151. int i;
  152. for(i=0;i<n;i++)
  153. {
  154. fread(&t,sizeof(friMesg),1,fp);
  155. p1=x;
  156. while(p1->next)
  157. {
  158. p1=p1->next;
  159. }
  160. p=(friMesg *)malloc(sizeof(friMesg));
  161. p->next=NULL;
  162. strcpy(p->rid,t.rid);
  163. strcpy(p->sid,t.sid);
  164. p->type=t.type;
  165. strcpy(p->mesg,t.mesg);
  166. p1->next=p;
  167. }
  168. fclose(fp);
  169. return x;
  170. }
  171. //获取系统时间
  172. char **get_time()
  173. {
  174. char **str=(char **)malloc(NUM*sizeof(char *));
  175. time_t t;
  176. struct tm * lt;
  177. time (&t);//获取Unix时间戳。
  178. lt = localtime (&t);//转为时间结构。
  179. sprintf ( str,"%04d/%02d/%02d %02d:%02d:%02d\n",lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);//输出结果
  180. return str;
  181. }
  182. //保存账户信息
  183. void saveclient()
  184. {
  185. FILE *fp;
  186. fp=fopen("counterMsg","w"); //打开文件
  187. if(fp==NULL)
  188. {
  189. printf("open error\n");
  190. return;
  191. }
  192. printf("账户个数=%d",count);
  193. fwrite(&count,sizeof(int),1,fp); //先保存账号个数
  194. cliMesg* p;
  195. p=head;
  196. if(p->next==NULL) //如果账号列表为空 , 关闭文件并退出函数
  197. {
  198. fclose(fp);
  199. return ;
  200. }
  201. p=p->next;
  202. //按结构体大小保存账号信息
  203. while(p)
  204. {
  205. fwrite(p,sizeof(cliMesg),1,fp);
  206. p=p->next;
  207. }
  208. printf("账号信息保存成功\n");
  209. fclose(fp);
  210. }
  211. //保存未查看的消息
  212. void savefile()
  213. {
  214. FILE *fp;
  215. fp=fopen("buffMsg","w");
  216. if(fp==NULL)
  217. {
  218. printf("open error\n");
  219. return;
  220. }
  221. printf("未查看信息个数=%d\n",urev_count);
  222. fwrite(&urev_count,sizeof(int),1,fp);
  223. friMesg *p;
  224. p=head1;
  225. if(p->next==NULL)
  226. {
  227. fclose(fp);
  228. return;
  229. }
  230. p=p->next;
  231. while(p)
  232. {
  233. fwrite(p,sizeof(cliMesg),1,fp);
  234. p=p->next;
  235. }
  236. printf("信息保存成功");
  237. fclose(fp);
  238. }
  239. //服务器上当前客户端id.txt保存聊天记录
  240. void savefile2(char str[1024],char id[20])
  241. {
  242. FILE *fp;
  243. char ch[1024];
  244. sprintf(ch,"./%s/%s.txt",id,id);
  245. fp=fopen(ch,"a+");
  246. if(fp==NULL) //打开错误关闭程序
  247. return ;
  248. memset(ch,0,1024);
  249. strcat(str,"\n"); //txt文档每行句末尾加特殊换行符
  250. strcpy(ch,str);
  251. fwrite(ch,strlen(ch),1,fp);
  252. printf("聊天记录保存成功\n");
  253. fclose(fp);
  254. }
  255. //帐号合格性检查
  256. int isnum1(char s[20])
  257. {
  258. int i=0;
  259. while(s[i])
  260. {
  261. if(!isdigit(s[i]))
  262. {
  263. return 0;
  264. }
  265. i++;
  266. }
  267. if(i<11)
  268. {
  269. return 0;
  270. }
  271. return 1;
  272. }
  273. //用户注册
  274. void add(int fd)
  275. {
  276. cliMesg *p1,*p,*p2;
  277. int leap=0; //标识符,账号是否能正确注册
  278. p=(cliMesg *)malloc(SIZE);
  279. if(p==NULL)
  280. return;
  281. char str[256];
  282. char str1[256];
  283. memset(str,0,sizeof(str));
  284. memset(str1,0,sizeof(str1));
  285. strcpy(str,"请输入您要注册的手机号");
  286. send(fd,str,strlen(str),0);
  287. memset(str,0,sizeof(str));
  288. recv(fd,str,sizeof(str),0);
  289. strcpy(str1,str);
  290. if(!isnum1(str)) //判断是否纯数字账号
  291. {
  292. memset(str,0,sizeof(str));
  293. strcpy(str,"请输入正确的手机号\n");
  294. send(fd,str,strlen(str),0);
  295. return;
  296. }
  297. p1=head;
  298. //判断注册账户是否存在
  299. while(p1->next)
  300. {
  301. if(strcmp(p1->next->id,str)==0)
  302. {
  303. leap=1;
  304. break;
  305. }
  306. p1=p1->next;
  307. }
  308. if(leap==1)
  309. {
  310. memset(str,0,sizeof(str));
  311. strcpy(str,"账号重复\n");
  312. send(fd,str,strlen(str),0);
  313. return;
  314. }
  315. //正常注册
  316. strcpy(p->id,str1);
  317. memset(str,0,sizeof(str));
  318. strcpy(str,"请输入密码");
  319. send(fd,str,strlen(str),0);
  320. memset(str,0,sizeof(str));
  321. recv(fd,str,sizeof(str),0);
  322. strcpy(p->passwd,str);
  323. memset(str,0,sizeof(str));
  324. strcpy(str,"请输入昵称");
  325. send(fd,str,strlen(str),0);
  326. memset(str,0,sizeof(str));
  327. recv(fd,str,sizeof(str),0);
  328. strcpy(p->name,str);
  329. p1=head;
  330. while(p1->next)
  331. {
  332. p1=p1->next;
  333. }
  334. p1->next=p;
  335. p->hys=0;
  336. p->online=0;
  337. p->fd=-5;
  338. p->next=NULL;
  339. memset(str,0,sizeof(str));
  340. strcpy(str,"注册成功,您可以登录了\n");
  341. send(fd,str,strlen(str),0);
  342. count++; //全局变量账号数量+1
  343. //保存账户信息
  344. saveclient();
  345. memset(str,0,sizeof(str));
  346. sprintf(str,"mkdir ./%s",p->id);
  347. system(str);
  348. }
  349. //账户匹配检查
  350. int check_iscount(char id[20])
  351. {
  352. cliMesg *p;
  353. if(head->next==NULL)
  354. {
  355. return 0;
  356. }
  357. p=head->next;
  358. while(p)
  359. {
  360. if(strcmp(id,p->id)==0)
  361. {
  362. return 1;
  363. }
  364. p=p->next;
  365. }
  366. return 0;
  367. }
  368. //密码匹配检查
  369. int check_countpasswd(char id[20],char passwd[20])
  370. {
  371. cliMesg *p;
  372. if(head->next==NULL)
  373. {
  374. return 0;
  375. }
  376. p=head->next;
  377. while(p)
  378. {
  379. if(strcmp(id,p->id)==0 && strcmp(passwd,p->passwd)==0)
  380. {
  381. return 1;
  382. }
  383. p=p->next;
  384. }
  385. return 0;
  386. }
  387. //判断是否在线
  388. int countOnline(char id[20])
  389. {
  390. cliMesg *p;
  391. p=head;
  392. while(p)
  393. {
  394. if((strcmp(p->id,id)==0) && p->online==1)
  395. {
  396. return 1;
  397. }
  398. p=p->next;
  399. }
  400. return 0;
  401. }
  402. //好友列表
  403. void list_friends(int fd,char id[20])
  404. {
  405. char sendbuf[1024]={0};
  406. cliMesg *p,*p1;
  407. int cnt=0;
  408. p=head;
  409. p=p->next;
  410. while(p)
  411. {
  412. if(strcmp(p->id,id)==0)
  413. {
  414. break;
  415. }
  416. p=p->next;
  417. }
  418. int num=p->hys;
  419. if(num==0)
  420. {
  421. memset(sendbuf,0,sizeof(sendbuf));
  422. strcpy(sendbuf,"好友列表为空");
  423. send(fd,sendbuf,strlen(sendbuf),0);
  424. return;
  425. }
  426. memset(sendbuf,0,sizeof(sendbuf));
  427. strcpy(sendbuf,"***************好友列表***************");
  428. send(fd,sendbuf,strlen(sendbuf),0);
  429. int i;
  430. for(i=0;i<num;i++)
  431. {
  432. p1=head->next;
  433. char str[20]={0};
  434. while(p1)
  435. {
  436. if(strcmp(p1->id,p->hy[i])==0)
  437. {
  438. strcpy(str,p1->name);
  439. break;
  440. }
  441. p1=p1->next;
  442. }
  443. memset(sendbuf,0,sizeof(sendbuf));
  444. if(p1->online==1)
  445. cnt++;
  446. sprintf(sendbuf,"%d 好友账号[%s],昵称[%s],[%d]\n",i+1,p->hy[i],str,p1->online);
  447. send(fd,sendbuf,strlen(sendbuf),0);
  448. }
  449. memset(sendbuf,0,sizeof(sendbuf));
  450. sprintf(sendbuf,"在线好友个数=%d\n",cnt);
  451. send(fd,sendbuf,strlen(sendbuf),0);
  452. memset(sendbuf,0,sizeof(sendbuf));
  453. strcpy(sendbuf,"**************************************");
  454. send(fd,sendbuf,strlen(sendbuf),0);
  455. }
  456. //查找已加好友
  457. void find_friends(int fd,char id[20])
  458. {
  459. cliMesg *p,*p1;
  460. p=head;
  461. char sendbuf[1024]={0};
  462. char recvbuf[1024]={0};
  463. char find_id[1024]={0};
  464. strcpy(sendbuf,"请输入您要查找的手机号");
  465. send(fd,sendbuf,strlen(sendbuf),0);
  466. recv(fd,find_id,sizeof(find_id),0);
  467. //查找手机号是否存在
  468. if(check_iscount(find_id)==0)
  469. {
  470. memset(sendbuf,0,sizeof(sendbuf));
  471. strcpy(sendbuf,"此号码不存在");
  472. send(fd,sendbuf,strlen(sendbuf),0);
  473. return;
  474. }
  475. //查找自己是否有该好友
  476. p=p->next;
  477. while(p)
  478. {
  479. if(strcmp(p->id,id)==0)
  480. {
  481. break;
  482. }
  483. p=p->next;
  484. }
  485. if(p->hys==0)
  486. {
  487. memset(sendbuf,0,sizeof(sendbuf));
  488. strcpy(sendbuf,"没有此好友");
  489. send(fd,sendbuf,strlen(sendbuf),0);
  490. }
  491. int i;
  492. int num=p->hys;
  493. for(i=0;i<num;i++)
  494. {
  495. //如果找到
  496. if(strcmp(p->hy[i],find_id)==0)
  497. {
  498. //将其昵称取出
  499. p1=head->next;
  500. char str[20]={0};
  501. while(p1)
  502. {
  503. if(strcmp(p1->id,find_id)==0)
  504. {
  505. strcpy(str,p1->name);
  506. break;
  507. }
  508. p1=p1->next;
  509. }
  510. memset(sendbuf,0,sizeof(sendbuf));
  511. sprintf(sendbuf,"该好友账户为%s,昵称为%s",find_id,str);
  512. send(fd,sendbuf,strlen(sendbuf),0);
  513. }
  514. }
  515. }
  516. //删除好友
  517. void del_friends(int fd,char id[20])
  518. {
  519. cliMesg *p,*p1;
  520. int i,leap=0;
  521. char sendbuf[1024]={0};
  522. char recvbuf[1024]={0};
  523. p=he
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/252261
推荐阅读
相关标签
  

闽ICP备14008679号