请选择 进入手机版 | 继续访问电脑版
查看: 397|回复: 0

[云计算] Linux下的聊天工具

725

主题

725

帖子

2188

积分

猿er

Rank: 1

积分
2188
发表于 2016-8-14 17:58:23
首先感谢T0rnad0,是在他代码的基础改得 http://www.oschina.net/code/snippet_128508_4114
可以群发信息,一对一发送文件,根据用户名查询ID
刚接触写的不是很好 请多多指教!
  1. /*
  2. *i.h is a used for creating a library
  3. *for server client
  4. *Mar 18 2010
  5. *
  6. */
  7. #ifndef _I_H
  8. #define _I_H
  9. #include <math.h>
  10. #include <stdio.h>
  11. #include <sys/socket.h>
  12. #include <arpa/inet.h>
  13. #include <netinet/in.h>
  14. #include <unistd.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include <stdlib.h>
  19. #include <errno.h>
  20. #include <string.h>
  21. #include <inttypes.h>
  22. #include <time.h>
  23. #include <sys/ioctl.h>
  24. #include <net/if.h>
  25. #include <signal.h>
  26. #include <ncurses.h>
  27. #include <math.h>
  28. #define SEVR_IP "127.0.0.1"
  29. #define SEVR_PORT 8081
  30. #define CNTNT_LEN 150
  31. #define MSG_LEN sizeof(struct msg)
  32. #define ADDR_LEN sizeof(struct sockaddr)
  33. #define USR_LEN sizeof(struct user)
  34. #define PRT_LEN 8
  35. #define HSTR_LEN sizeof(struct chat_history)
  36. #define MAXLINE 1024
  37. #define FILE_LEN 20 //文件路径名的最大长度
  38. /* declare Global variables */
  39. int mainfd;/* used as chat histroy file handle*/
  40. int sockfd;/* used as socket local handle */
  41. int count;
  42. struct sockaddr_in server;
  43. /* msg is used for communicating message */
  44. struct msg
  45. {
  46. int flag; /* flag meaning:1:ordinary; 2:log msg; 3:reg msg, 4:file,5:group,6:query msg*/
  47. int id_from;
  48. int id_to; /*-1表示是群发的*/
  49. char content[CNTNT_LEN];
  50. char append[10];
  51. };
  52. /* user is used information list */
  53. struct user
  54. {
  55. int id;
  56. char name[10];
  57. char password[10];
  58. char *p_chatlog;
  59. struct sockaddr user_addr;
  60. };
  61. /* chat_history used for reading chat history */
  62. struct chat_history
  63. {
  64. char content[CNTNT_LEN];
  65. char time[25];
  66. int to;
  67. int from;
  68. int count;
  69. };
  70. /* i_functions below is funtions needed by both client and sever */
  71. extern int i_saveto_chat(struct msg *pmsg);
  72. int i_clean_stdin ()
  73. {
  74. while ('\n' == getchar())
  75. {
  76. continue;
  77. }
  78. return(0);
  79. }
  80. int i_print(char *pmsg, int size)
  81. {
  82. int i = 1;
  83. for (i; i<= size; i++)
  84. {
  85. if (*pmsg != '\n')
  86. {
  87. printf("%c", *pmsg);
  88. pmsg ++;
  89. }
  90. else
  91. {
  92. return(0);
  93. }
  94. }
  95. return(0);
  96. }
  97. int i_input(char *p_input)
  98. {
  99. char c = '\0';
  100. int i;
  101. for (i = 0; i < CNTNT_LEN; i++)
  102. {
  103. p_input[i] = getchar();
  104. if (p_input[i] =='\n')
  105. {
  106. return(0);
  107. }
  108. }
  109. printf("you have input long enough!\n");
  110. return(0);
  111. }
  112. int i_socket(int domain, int type, int protocol)
  113. {
  114. int fd;
  115. if ((fd = socket(domain, type, protocol)) == -1)
  116. {
  117. perror("creat socket error:");
  118. exit(1);
  119. }
  120. return(fd);
  121. }
  122. int i_bind(int fd, const struct sockaddr *addr, int namelen)
  123. {
  124. if (-1 == bind(fd, addr, namelen))
  125. {
  126. perror("i_bind error:");
  127. exit(1);
  128. }
  129. return (0);
  130. }
  131. int i_recvfrom(int fd, void *buf, size_t len, int flags,
  132. struct sockaddr *addr, int *size)
  133. {
  134. if (-1 == recvfrom(fd, buf, len, flags, addr, size))
  135. {
  136. perror("i_recvfrom error:");
  137. exit(1);
  138. }
  139. return(0);
  140. }
  141. int i_sendto(int fd, void *buf, size_t len, int flags,
  142. struct sockaddr *addr, int size)
  143. {
  144. if (-1 == sendto(fd, buf, len, flags, addr, size))
  145. {
  146. perror("i_sendto error");
  147. exit(1);
  148. }
  149. return (0);
  150. }
  151. int i_open(const char *pathname, int flags)
  152. {
  153. int fd;
  154. if ((fd = open(pathname, flags)) == -1)
  155. {
  156. perror("open_failed");
  157. exit(1);
  158. }
  159. return (fd);
  160. }
  161. int i_read(int fd, void *msg, int len)
  162. {
  163. if(-1 == read(fd, msg, len))
  164. {
  165. perror("i_read error");
  166. exit(1);
  167. }
  168. return(0);
  169. }
  170. int i_write(int fd, void *msg, int len)
  171. {
  172. if (-1 == write(fd, msg, len))
  173. {
  174. perror("i_write error");
  175. exit(0);
  176. }
  177. return(0);
  178. }
  179. /* init a socket,file and server addr */
  180. int i_init()
  181. {
  182. mainfd = i_open("./chat_log", O_RDWR|O_CREAT);
  183. sockfd = i_socket(AF_INET, SOCK_DGRAM, 0);
  184. /* initialize server address */ //先把服务器的地址设置成本机地址
  185. bzero(&server, sizeof(server));
  186. server.sin_family = AF_INET;
  187. inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);
  188. // inet_pton(AF_INET, "192.168.1.100", &server.sin_addr);
  189. server.sin_port = htons(SEVR_PORT);
  190. perror("init");
  191. return (0);
  192. }
  193. char *i_get_time()
  194. {
  195. time_t time_now;
  196. time(&time_now);
  197. return(ctime(&time_now));
  198. }
  199. int i_lseek(int fd, off_t size, int position)
  200. {
  201. if (-1 == lseek(fd, size, position))
  202. {
  203. perror("seek error");
  204. exit(1);
  205. }
  206. return(0);
  207. }
  208. int i_saveto_chat(struct msg *pmsg)
  209. {
  210. struct chat_history hstr;
  211. bzero(&hstr, HSTR_LEN);
  212. count = count + 1;
  213. hstr.count =count;
  214. hstr.from = pmsg->id_from;
  215. hstr.to = pmsg->id_to;
  216. strncpy(hstr.content, pmsg->content, CNTNT_LEN);
  217. strncpy(hstr.time, i_get_time(), 25);
  218. i_lseek(mainfd, 0, SEEK_END);
  219. i_write(mainfd, &hstr, HSTR_LEN);
  220. return(0);
  221. }
  222. int i_print_history(int len, int i)
  223. {
  224. struct chat_history chat_reader;
  225. int j;
  226. int position;
  227. bzero(&chat_reader, HSTR_LEN);
  228. if (i != 0)
  229. {
  230. position = len*i*HSTR_LEN;
  231. i_lseek(mainfd, position, SEEK_END);
  232. }
  233. else
  234. {
  235. position = len*i*HSTR_LEN;
  236. i_lseek(mainfd, HSTR_LEN, SEEK_SET);
  237. }
  238. for (j = 1; j <= len; j++)
  239. {
  240. i_read(mainfd, &chat_reader, HSTR_LEN);
  241. printf("\n#item%d:id%dto id%d \n", j,
  242. chat_reader.from, chat_reader.to);
  243. i_print(chat_reader.content, CNTNT_LEN);
  244. printf("\n Time:%s\n", chat_reader.time);
  245. }
  246. return(0);
  247. }
  248. #endif
复制代码
  1. /*
  2. *title: client.c
  3. *start_time: Mar.18 2011
  4. *end_time: Apr.8 2011
  5. */
  6. #include "i.h"
  7. #define START_PORT 8089
  8. #define FILE_PORT 8093
  9. struct sockaddr_in my_addr;
  10. int my_id;
  11. int my_log();/* declare funtion*/
  12. int pd[2]; //建立管道用从子进程向父进程产当前收到的消息
  13. /* */
  14. int i_send_msg()
  15. {
  16. int id;
  17. struct msg the_msg;
  18. char end = '@';
  19. printf("input recver id:");
  20. scanf("%d", &id);
  21. getchar(); //去掉scanf后面的那个回车建
  22. printf("\ninput content:");
  23. i_input(the_msg.content);
  24. char flag = 'y';
  25. if (1)
  26. {
  27. the_msg.flag = 1;
  28. the_msg.id_from = my_id;
  29. the_msg.id_to = id;
  30. i_sendto(sockfd, &the_msg, sizeof(struct msg), 0,
  31. (struct sockaddr*)&server, sizeof(struct sockaddr));
  32. i_saveto_chat(&the_msg); /* save to history */
  33. printf("send to id:%d success.\n", id);
  34. return(0);
  35. }
  36. else
  37. return(1);
  38. return(0);
  39. }
  40. int send_query_msg() /*查询消息记录不保存*/
  41. {
  42. printf("\n input the usr name:");
  43. char name[10]={0};
  44. scanf("%s",name);
  45. struct msg the_msg;
  46. the_msg.flag=6;
  47. the_msg.id_from=my_id;
  48. the_msg.id_to=0;
  49. strcpy(the_msg.content,name);
  50. i_sendto(sockfd,&the_msg,sizeof(struct msg),0,
  51. (struct sockaddr*)&server, sizeof(struct sockaddr));
  52. printf("query msg send success!\n");
  53. return (0);
  54. }
  55. int send_group_msg()
  56. {
  57. struct msg the_msg;
  58. printf("\n input the content:");
  59. getchar();
  60. i_input(the_msg.content);
  61. the_msg.flag=5;
  62. the_msg.id_from=my_id;
  63. the_msg.id_to=-1; //-1表示群发的信息
  64. i_sendto(sockfd,&the_msg,sizeof(struct msg),0,(struct sockaddr*)&server,sizeof(struct sockaddr));
  65. i_saveto_chat(&the_msg);
  66. printf("send all user success!\n");
  67. return (0);
  68. }
  69. int reply()
  70. {
  71. struct msg s;
  72. read(pd[0],&s,MSG_LEN); //从管道中读取信息
  73. struct msg the_msg;
  74. the_msg.flag=1;
  75. the_msg.id_from=my_id;
  76. the_msg.id_to=s.id_from;
  77. getchar();
  78. printf("\ninput the msg content:");
  79. i_input(the_msg.content);
  80. i_sendto(sockfd, &the_msg, sizeof(struct msg), 0,
  81. (struct sockaddr*)&server, sizeof(struct sockaddr));
  82. i_saveto_chat(&the_msg);
  83. printf("reply the msg success!\n");
  84. return(0);
  85. }
  86. int send_file()
  87. {
  88. int id;
  89. struct msg the_msg;
  90. memset(&the_msg,0,sizeof(struct msg));
  91. printf("input recver id:");
  92. scanf("%d", &id);
  93. getchar(); //去掉scanf后面的那个回车建
  94. printf("\ninput send file path (less %d char):",FILE_LEN);
  95. scanf("%s",the_msg.content);
  96. char filename[FILE_LEN+1]={0};
  97. strcpy(filename,the_msg.content);
  98. the_msg.flag=4;
  99. the_msg.id_from=my_id;
  100. the_msg.id_to=id;
  101. // i_sendto(sockfd,&the_msg,sizeof(struct msg),0,(struct sockaddr*)&server,sizeof(struct sockaddr));
  102. /*打开本地文件*/
  103. int fd=open(filename,O_RDWR);
  104. int size=lseek(fd,0,SEEK_END);/*文件大小*/
  105. lseek(fd,0,SEEK_SET);
  106. /*等待接收文件的一方来连接*/
  107. // printf("wait connect....\n");
  108. int sd;
  109. if((sd=socket(AF_INET,SOCK_STREAM,0))==-1)
  110. {
  111. printf("sock creat error\n");
  112. return 0;
  113. }
  114. struct sockaddr_in addr;
  115. memcpy(&addr,&my_addr,sizeof(struct sockaddr_in));
  116. addr.sin_family=AF_INET;
  117. addr.sin_port = htons(FILE_PORT);
  118. const int reuse = 1;
  119. setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
  120. if(bind(sd,(struct sockaddr*)&addr,sizeof(struct sockaddr))==-1)
  121. {
  122. printf("bind sock error\n");
  123. return 0;
  124. }
  125. if(listen(sd,1)==-1)
  126. {
  127. printf("listen sock error\n");
  128. return 0;
  129. }
  130. int ad,len;
  131. struct sockaddr_in client_addr;
  132. /*先将文件信息发送个服务器*/
  133. i_sendto(sockfd,&the_msg,sizeof(struct msg),0,(struct sockaddr*)&server,sizeof(struct sockaddr));
  134. i_saveto_chat(&the_msg);
  135. if((ad=accept(sd,(struct sockaddr*)&client_addr,&len))==-1)
  136. {
  137. printf("accept socket error\n");
  138. return 0;
  139. }
  140. char buf[MAXLINE];
  141. int readsize=0;
  142. printf("start send file\n");
  143. while(readsize<size)
  144. {
  145. memset(buf,0,MAXLINE);
  146. readsize+=read(fd,buf,MAXLINE);
  147. write(ad,buf,MAXLINE);
  148. }
  149. close(fd);
  150. close(ad);
  151. close(sd);
  152. printf("file send success!\n");
  153. return(0);
  154. }
  155. /**/
  156. /* start:initialize */
  157. int init()
  158. {
  159. struct ifreq req;
  160. struct sockaddr_in *host;
  161. int port;
  162. i_init();
  163. /* init user addr */
  164. bzero(&my_addr, sizeof(struct sockaddr));
  165. my_addr.sin_family = AF_INET;
  166. strcpy(req.ifr_name, "lo");
  167. if ( ioctl(sockfd, SIOCGIFADDR, &req) < 0 ) /* get local ip address */
  168. {
  169. perror("get local ip error");
  170. exit(1);
  171. }
  172. host = (struct sockaddr_in*)&(req.ifr_addr);
  173. printf("ip: %s\n", inet_ntoa(host->sin_addr));
  174. memcpy(&my_addr, (struct sockaddr_in*)&(req.ifr_addr),
  175. sizeof(struct sockaddr_in));
  176. port = START_PORT;
  177. do
  178. {
  179. port++;
  180. my_addr.sin_port = htons(port);
  181. bind(sockfd, (struct sockaddr*)&my_addr,
  182. sizeof(struct sockaddr));
  183. }
  184. while (errno == EADDRINUSE);
  185. struct chat_history apple;
  186. memset(&apple, 'b', HSTR_LEN);
  187. i_lseek(mainfd, 0, SEEK_SET);
  188. apple.count = 0;
  189. i_write(mainfd, &apple, HSTR_LEN);
  190. i_lseek(mainfd, -HSTR_LEN, SEEK_END);
  191. i_read(mainfd, &apple, HSTR_LEN);
  192. count = apple.count;
  193. printf("port:%d\n", port);
  194. printf("init successful!!!\n");
  195. return(0);
  196. }
  197. /* end:initialize */
  198. /* start:chat_history*/
  199. int get_page_size()
  200. {
  201. struct chat_history page_size_reader;
  202. i_lseek(mainfd, -HSTR_LEN, SEEK_END);
  203. i_read(mainfd, &page_size_reader, HSTR_LEN);
  204. return(page_size_reader.count);
  205. }
  206. int read_chat_history()
  207. {
  208. printf("****char*history***");
  209. printf("(n-nextpage; p-prepage; q-quit)\n");
  210. int page_num;/* */
  211. int remains;
  212. int berry = get_page_size();
  213. page_num = berry / 8;
  214. remains = berry % 8;
  215. if (remains != 0)
  216. page_num ++;
  217. else
  218. page_num = page_num;
  219. printf("there are %d page total %d items",
  220. page_num, berry);
  221. int i = -1;
  222. while (1)
  223. {
  224. char flag;
  225. if ((berry + i*8) >= 0)
  226. {
  227. printf("(%d~%d)\n", (berry + i*8), (berry + (i+1)*8));
  228. i_print_history(PRT_LEN, i);
  229. printf("@@@\n");
  230. while ('\n' == (flag = getchar()))
  231. {
  232. }
  233. switch (flag)
  234. {
  235. case 'p' :
  236. i--;
  237. break;
  238. case 'n' :
  239. i++;
  240. break;
  241. case 'q' :
  242. return(0);
  243. default :
  244. break;
  245. }
  246. if (i >= 0)
  247. {
  248. printf("have at the end!\n");
  249. printf("return to menu!\n");
  250. }
  251. }
  252. else
  253. {
  254. printf("(1~%d)\n", remains);
  255. i_print_history(remains, 0);
  256. printf("#########over##############\n");
  257. return(0);
  258. }
  259. }
  260. return(0);
  261. }
  262. /* end:chat_history*/
  263. /* start:exit_sys*/
  264. void exit_sys()
  265. {
  266. close(sockfd);
  267. close(mainfd);
  268. kill(0, SIGABRT);
  269. exit(0);
  270. }
  271. /* end:exit_sys*/
  272. /* start:menu*/
  273. int print_menu()
  274. {
  275. printf("\n--------------help--menu----------------\n");
  276. printf("\t h--help munu\n");
  277. printf("\t s--send message\n");
  278. printf("\t r--reply to\n");
  279. printf("\t c--chat history\n");
  280. printf("\t f--send files\n");
  281. printf("\t q--query id through name\n"); /**/
  282. printf("\t g--send group message");
  283. printf("\t e--exit the system\n");
  284. printf("----------------help--menu----------------\n");
  285. }
  286. int get_input(char *command)
  287. {
  288. printf(">");
  289. scanf("%c", command);
  290. return(1);
  291. }
  292. int menu()
  293. {
  294. /* to avoid the output at mixed with the sub process */
  295. sleep(1);
  296. print_menu();
  297. char command;
  298. while (1 == get_input(&command))
  299. {
  300. switch(command)
  301. {
  302. case 'h':
  303. print_menu();
  304. break;
  305. case 's':
  306. i_send_msg();
  307. break;
  308. case 'r':
  309. reply();
  310. break;
  311. case 'f':
  312. send_file();
  313. break;
  314. case 'c':
  315. read_chat_history();
  316. break;
  317. case 'q':
  318. send_query_msg();
  319. break;
  320. case 'g':
  321. send_group_msg();
  322. break;
  323. case 'e':
  324. exit_sys();
  325. break;
  326. default :
  327. printf(">");
  328. break;
  329. }
  330. }
  331. return(0);
  332. }
  333. /* end:menu*/
  334. /*file msg recv*/
  335. int file_msg_recv(struct msg *pmsg)
  336. { /*主动去连接发送者*/
  337. printf("start recv file\n");
  338. /*拆分content中的文件名和ip地址*/
  339. /* name 保存文件名不包含路径
  340. ip_addr 保存ip地址*/
  341. char name[FILE_LEN+1]={0};
  342. char *p=strrchr(pmsg->content,'$');
  343. int len=p-pmsg->content;
  344. strncpy(name,pmsg->content,len);
  345. char *s=++p;
  346. char ip_addr[20]={0};
  347. strcpy(ip_addr,s);
  348. s=strrchr(name,'/');
  349. if(s==NULL)
  350. s=name;
  351. else
  352. s++;
  353. int fd;
  354. if((fd=open(name,O_RDWR|O_CREAT))==-1)
  355. {
  356. printf("creat file error\n");
  357. return 0;
  358. }
  359. int sd;
  360. if((sd=socket(AF_INET,SOCK_STREAM,0))==-1)
  361. {
  362. printf("sock creat error\n");
  363. return 0;
  364. }
  365. struct sockaddr_in addr;
  366. inet_pton(AF_INET,&ip_addr,&addr.sin_addr);
  367. addr.sin_family=AF_INET;
  368. addr.sin_port = htons(FILE_PORT);
  369. if(-1==connect(sd,(struct sockaddr*)&addr,sizeof(struct sockaddr)))
  370. {
  371. printf("connect error!\n");
  372. return 0;
  373. }
  374. char buf[MAXLINE];
  375. memset(buf,0,MAXLINE);
  376. printf("start recv\n");
  377. int rs;
  378. while((rs=read(sd,buf,MAXLINE))!=0)
  379. {
  380. write(fd,buf,rs);
  381. memset(buf,0,MAXLINE);
  382. }
  383. printf("file recv success!\n");
  384. close(fd);
  385. close(sd);
  386. return 0;
  387. }
  388. /* start:message contol :send_msg and recv_msg */
  389. int ordnary_msg_recv(struct msg *pmsg)
  390. {
  391. char time_info[25];
  392. char end_symble;
  393. end_symble = '&';
  394. /* handle the msg */
  395. printf("Message:from %s(id%d) to U:\n", pmsg->append, pmsg->id_from);
  396. i_print(pmsg->content, MSG_LEN);
  397. printf("\n\t%s", i_get_time());
  398. return(0);
  399. }
  400. int query_msg_recv (struct msg *msg_recv)
  401. {
  402. printf("%s\n",msg_recv->content);
  403. return 0;
  404. }
  405. int group_msg_recv(struct msg *pmsg)
  406. {
  407. char time_info[25];
  408. char end_symble;
  409. end_symble = '&';
  410. /* handle the msg */
  411. printf("Message:from %s(id%d) to Our:\n", pmsg->append, pmsg->id_from);
  412. i_print(pmsg->content, MSG_LEN);
  413. printf("\n\t%s", i_get_time());
  414. return(0);
  415. }
  416. int handle_msg(struct msg *pmsg)
  417. {
  418. if (pmsg->flag == 1)
  419. {
  420. ordnary_msg_recv(pmsg);
  421. return(0);
  422. }
  423. else if (pmsg->flag >= 4)
  424. {
  425. file_msg_recv(pmsg);
  426. return(0);
  427. }
  428. return(0);
  429. }
  430. int listen_msg()
  431. {
  432. struct msg msg_recv;
  433. struct sockaddr addr_recv;
  434. int len = ADDR_LEN;
  435. printf("begin listen...\n");
  436. for ( ; ; )
  437. {
  438. i_recvfrom(sockfd, &msg_recv, MSG_LEN, 0,
  439. &addr_recv, &len);
  440. write(pd[1],&msg_recv,MSG_LEN); //把当前收到的消息传递给父进程,当其选择reply的时候需要知道地方的id等
  441. i_saveto_chat(&msg_recv); /* save to history */ /*传送文件的时候保存的是文件的名字*/
  442. if(msg_recv.flag==4)
  443. file_msg_recv(&msg_recv);
  444. else if(msg_recv.flag==6)
  445. query_msg_recv(&msg_recv);
  446. else if(msg_recv.flag==5)
  447. group_msg_recv(&msg_recv);
  448. else
  449. ordnary_msg_recv(&msg_recv);
  450. }
  451. }
  452. /* end:message contol*/
  453. /* start:log process :login and regist */
  454. int login()
  455. {
  456. /* input id:*/
  457. printf("*****login>>\n");
  458. printf("id:");
  459. scanf("%d", &my_id);
  460. /* input password*/
  461. char password[15];
  462. printf("\npassword(*less 15 char):\n");
  463. scanf("%s", password);
  464. getchar();
  465. /* send login information */
  466. struct msg log_msg;
  467. bzero(&log_msg, MSG_LEN);
  468. log_msg.flag = 2;
  469. log_msg.id_from = my_id;
  470. log_msg.id_to = 0;
  471. strncpy(log_msg.content, password, 15);
  472. i_saveto_chat(&log_msg); /* save to history */
  473. i_sendto(sockfd, (struct msg*)&log_msg, MSG_LEN, 0,
  474. (struct sockaddr*)&server, sizeof(struct sockaddr));
  475. /* after input msg ,wait for server respond*/
  476. struct sockaddr in_addr;
  477. int len = ADDR_LEN;
  478. i_recvfrom(sockfd, (struct msg*)&log_msg, MSG_LEN,0,
  479. &in_addr, &len);
  480. if (2 == log_msg.flag)
  481. {
  482. printf("login success\n");
  483. return(0);
  484. }
  485. else
  486. {
  487. printf("login error:%s\n", log_msg.content);
  488. printf("please relog..\n");
  489. menu();
  490. }
  491. return (0);
  492. }
  493. int regist()
  494. {
  495. printf("*****regist>>\n");
  496. /* input chat name */
  497. char name[10];
  498. bzero(name, 10);
  499. printf("input your chat name(less 8 char):");
  500. scanf("%s", name);
  501. //name[9] = ';'; /* add a ; symbol in the end of name */
  502. /* input password */
  503. char password[15];
  504. bzero(password, 15);
  505. printf("\ninput your password(less 14 char):");
  506. scanf("%s", password);
  507. /* send regist information*/
  508. struct msg reg_msg;
  509. bzero(&reg_msg, MSG_LEN);
  510. reg_msg.flag = 3;
  511. reg_msg.id_from = 0;
  512. reg_msg.id_to = 0;
  513. bzero(reg_msg.content, CNTNT_LEN);
  514. strncpy(reg_msg.content, name, 10);
  515. strncpy(&(reg_msg.content[10]), password, 15);
  516. reg_msg.content[25] = '\n';
  517. i_saveto_chat(&reg_msg); /* save to history */
  518. /* send regist informatin to server */
  519. i_sendto(sockfd, (struct msg*)&reg_msg, sizeof(struct msg), 0,
  520. (struct sockaddr*)&server, ADDR_LEN);
  521. /* after input msg ,wait for server respond*/
  522. printf("wating for server reply...\n");
  523. struct sockaddr in_addr;
  524. struct msg msg_back;
  525. int len = ADDR_LEN;
  526. bzero(&in_addr, ADDR_LEN);
  527. bzero(&msg_back, MSG_LEN);
  528. i_recvfrom(sockfd,(struct msg*)&msg_back, MSG_LEN,0,
  529. &in_addr, &len);
  530. /* check whether pass */
  531. if (3 != msg_back.flag)
  532. {
  533. printf("error: %s \n", msg_back.content);
  534. exit(1);
  535. }
  536. else
  537. my_id = msg_back.id_to;
  538. printf("congratulate! you have regist"
  539. "id %s(id %d) success\n", msg_back.content, msg_back.id_to);
  540. login();
  541. return(0);
  542. }
  543. int my_log()
  544. {
  545. /* choose login or regist*/
  546. char flag;
  547. printf("are you want login or regist(l/r)\n");
  548. scanf("%c", &flag);
  549. getchar();
  550. switch (flag){
  551. case 'l' :
  552. login();
  553. break;
  554. case 'r' :
  555. regist();
  556. break;
  557. default :
  558. printf("error input\n");
  559. my_log();
  560. break;
  561. }
  562. return (0);
  563. }
  564. /* end:log */
  565. int main()
  566. {
  567. init();
  568. printf("\n************welcome!************\n");
  569. my_log();
  570. pid_t pid;
  571. pipe(pd);//建立管道用从子进程向父进程产当前收到的消息
  572. switch (pid = fork())
  573. {
  574. case -1 :
  575. perror("fork error!\n");
  576. exit(1);
  577. break;
  578. case 0 :
  579. close(pd[0]);
  580. listen_msg();
  581. break;
  582. default :
  583. close(pd[1]);
  584. menu();
  585. break;
  586. }
  587. }
复制代码
  1. /*
  2. *title:server.c
  3. *content:server part
  4. *start time: Mar.25.2011
  5. *end time: Apr.8 2011
  6. */
  7. #include "i.h"
  8. int user_list_fd;
  9. /* start:initialization */
  10. int init()
  11. {
  12. i_init();
  13. user_list_fd = i_open("./user_list", O_RDWR|O_CREAT);
  14. struct user usr;
  15. /* init the user list file's fist user to 0*/
  16. memset((struct user*)&usr, '\0', sizeof(struct user));
  17. i_lseek(user_list_fd, 0, SEEK_SET);
  18. i_write(user_list_fd, (char*)&usr, USR_LEN);
  19. /* bind the struct sockaddr_in server to the sockfd */
  20. i_bind(sockfd, (struct sockaddr*)&server, ADDR_LEN);
  21. struct chat_history apple;
  22. bzero(&apple, HSTR_LEN);
  23. i_lseek(mainfd, 0, SEEK_SET);
  24. i_write(mainfd, &apple, HSTR_LEN);
  25. i_lseek(mainfd, -HSTR_LEN, SEEK_END);
  26. i_read(mainfd, &apple, HSTR_LEN);
  27. count = apple.count;
  28. return(0);
  29. }
  30. /* end:initialization */
  31. /* start:message control */
  32. int send_msg(struct msg *msg_recv, struct sockaddr *addr)
  33. {
  34. int i;
  35. struct user usr;
  36. /* a common message come */
  37. printf("a ordinar message come !\n");
  38. /*获取发送者的用户名*/
  39. i = msg_recv->id_from; //这里应该是id_from
  40. i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);
  41. i_read(user_list_fd, &usr, USR_LEN);
  42. strncpy(msg_recv->append, usr.name, 10);
  43. /*获取接收者的地址*/
  44. i=msg_recv->id_to;
  45. i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);
  46. i_read(user_list_fd, &usr, USR_LEN);
  47. i_sendto(sockfd, msg_recv, MSG_LEN, 0,
  48. &(usr.user_addr), ADDR_LEN);
  49. printf("id%d send a message to id%d sucess!\n", msg_recv->id_from, msg_recv->id_to);
  50. return(0);
  51. }
  52. int send_file_msg(struct msg *msg_recv, struct sockaddr *addr)
  53. {
  54. /*现在消息的content中只是文件的全路径名,得发送者的ip地址给接收者带过去*/
  55. int id;
  56. struct user usr;
  57. char ip_addr[20]={0};
  58. id=msg_recv->id_from;
  59. i_lseek(user_list_fd,id*USR_LEN,SEEK_SET);
  60. i_read(user_list_fd,&usr,USR_LEN);
  61. /*这里要把sockaddr转换成sockaddr_in*/
  62. struct sockaddr_in *sa=(struct sockaddr_in*)&usr.user_addr;
  63. inet_ntop(AF_INET,&(sa->sin_addr),ip_addr,sizeof(ip_addr));
  64. strcat(msg_recv->content,"$"); /*文件名与ip地址的分割符*/
  65. strcat(msg_recv->content,ip_addr);
  66. strncpy(msg_recv->append, usr.name, 10);
  67. i_lseek(user_list_fd, msg_recv->id_to*USR_LEN, SEEK_SET);
  68. i_read(user_list_fd, &usr, USR_LEN);
  69. i_sendto(sockfd, msg_recv, MSG_LEN, 0,
  70. &(usr.user_addr), ADDR_LEN);
  71. printf("id%d send a file to id%d sucess!\n", msg_recv->id_from, msg_recv->id_to);
  72. }
  73. int send_group_msg(struct msg *msg_recv,struct sockaddr* addr_recv)
  74. {
  75. struct user usr;
  76. /*获取发送者的用户名*/
  77. i_lseek(user_list_fd,msg_recv->id_from*USR_LEN,SEEK_SET);
  78. i_read(user_list_fd,&usr,USR_LEN);
  79. strncpy(msg_recv->append,usr.name,10);
  80. /*读取当前注册用户中最大的id*/
  81. i_lseek(user_list_fd,-USR_LEN,SEEK_END);
  82. i_read(user_list_fd,&usr,USR_LEN);
  83. /*注册的时候id是从小(1)到大依次注册的*/
  84. int i=1;
  85. int n=usr.id;
  86. for(i;i<=n;i++) //依次读取文件的每个用户的信息
  87. {
  88. i_lseek(user_list_fd,i*USR_LEN,SEEK_SET);
  89. i_read(user_list_fd, &usr, USR_LEN);
  90. if(usr.id!=msg_recv->id_from) /*群发不发给自己*/
  91. i_sendto(sockfd, msg_recv, MSG_LEN, 0,
  92. &(usr.user_addr), ADDR_LEN);
  93. }
  94. printf("id:%d群发信息成功!\n",msg_recv->id_from);
  95. return 0;
  96. }
  97. int send_query_msg(struct msg *msg_recv,struct sockaddr* addr_recv)
  98. {
  99. char name[10]={0};
  100. struct msg the_msg;
  101. the_msg.flag=6;
  102. strcpy(name,msg_recv->content); //要查询的用户名
  103. int usr_id=msg_recv->id_from;
  104. // 遍历所有用户查找
  105. struct user usr;
  106. i_lseek(user_list_fd, -USR_LEN, SEEK_END);
  107. i_read(user_list_fd,&usr,USR_LEN);
  108. /*注册的时候id是从小(1)到大依次注册的, 初始化的时候,用户文件一个位置是一个内容为空的用户信息,读取的时候从下一个开始*/
  109. int j=1;
  110. int n=usr.id;
  111. for(j;j<=n;j++) //依次读取文件的每个用户的信息
  112. {
  113. int r;r=lseek(user_list_fd, j*USR_LEN, SEEK_SET);
  114. read(user_list_fd,&usr,USR_LEN);
  115. if(!strcmp(usr.name,name))
  116. {
  117. sprintf(the_msg.content,"the usr id is:%d",usr.id);
  118. i_sendto(sockfd,&the_msg,MSG_LEN,0,addr_recv,ADDR_LEN);
  119. printf("the id:%d finish query!\n",usr_id);
  120. return 0;
  121. }
  122. }
  123. char buf[50]={0};
  124. sprintf(buf,"%s%s","no the usrname is",name);
  125. strcpy(the_msg.content,buf);
  126. i_sendto(sockfd,&the_msg,MSG_LEN,0,addr_recv,ADDR_LEN);
  127. printf("the id:%d not finish query!\n",usr_id);
  128. return 0;
  129. }
  130. int check_login(struct msg *msg_recv, struct sockaddr *addr)
  131. {
  132. int i = msg_recv->id_from;;
  133. struct user usr;
  134. /* a login requet */
  135. printf("a login request come!\n");
  136. /* get the id's information */
  137. i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);
  138. i_read(user_list_fd, &usr, USR_LEN);
  139. int n;
  140. n = strcmp(usr.password, msg_recv->content);
  141. /* 如果验证成功,则发送成功信息 */
  142. if (n == 0)
  143. {
  144. /* save user new address */
  145. i_lseek(user_list_fd, -USR_LEN, SEEK_CUR);
  146. usr.user_addr = *addr;
  147. i_write(user_list_fd, &usr, USR_LEN);
  148. /* tell user pass */
  149. i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,
  150. &(usr.user_addr), ADDR_LEN);
  151. }
  152. else
  153. {
  154. /* 出错的话的respond */
  155. if (0 != n)
  156. {
  157. printf("id %d login error.\n", i);
  158. bzero(msg_recv->content, CNTNT_LEN);
  159. msg_recv->flag = -1;
  160. i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,
  161. &(usr.user_addr), ADDR_LEN);
  162. }
  163. return(1);
  164. }
  165. printf("id:%d login sucess!\n", i);
  166. return(0);
  167. }
  168. int reg_user(struct msg *msg_recv, struct sockaddr *addr)
  169. {
  170. struct user usr;
  171. printf("a regit requet come:\n");
  172. /* find the last user and hava the please to add a new user */
  173. int n;
  174. i_lseek(user_list_fd, -USR_LEN, SEEK_END);
  175. i_read(user_list_fd, &usr, USR_LEN);
  176. /* 把新用户的信息赋值到usr然后填入到user list file中 */
  177. const char *name;
  178. const char *password;
  179. name = &(msg_recv->content[0]);
  180. password = &(msg_recv->content[10]);
  181. strcpy((usr.name), name);
  182. strcpy(usr.password, password);
  183. memcpy(&(usr.user_addr),addr, ADDR_LEN);
  184. usr.id = (usr.id + 1);
  185. i_lseek(user_list_fd, 0, SEEK_END);
  186. i_write(user_list_fd, &usr, USR_LEN);
  187. msg_recv->id_from = usr.id;
  188. /* regist to the user list then tell the user reg success */
  189. i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,
  190. addr, ADDR_LEN);
  191. printf("Id %d regist sucess!\n", usr.id);
  192. return(0);
  193. }
  194. int msg_cntl()
  195. {
  196. struct msg msg_recv;
  197. struct sockaddr addr_recv;
  198. printf("begin listen input...\n");
  199. int size = ADDR_LEN;
  200. for (;;)
  201. {
  202. bzero(&msg_recv, MSG_LEN);
  203. i_recvfrom(sockfd, &msg_recv, sizeof(struct msg), 0,
  204. &addr_recv, &size);
  205. printf("message received...\n");
  206. i_saveto_chat(&msg_recv);
  207. switch (msg_recv.flag)
  208. {
  209. case 1 :
  210. send_msg(&msg_recv,(struct sockaddr*)&addr_recv);/* send ordinary chat */
  211. break;
  212. case 2 :
  213. check_login(&msg_recv, (struct sockaddr*)&addr_recv);
  214. break;
  215. case 3 :
  216. reg_user(&msg_recv, (struct sockaddr*)&addr_recv);
  217. break;
  218. case 4:
  219. send_file_msg(&msg_recv,(struct sockaddr*)&addr_recv);
  220. /*发送给要接收文件的用户 让其建立,绑定,监听tcp连接,等着要发送文件的用户去建立连接*/
  221. break;
  222. case 5:
  223. send_group_msg(&msg_recv,(struct sockaddr*)&addr_recv);//group-msg
  224. break;
  225. case 6:
  226. send_query_msg(&msg_recv,(struct sockaddr*)&addr_recv); /*根据用户名查询用户id的消息*/
  227. break;
  228. default :
  229. break;
  230. }
  231. }
  232. return(0);
  233. }
  234. /* end:message control*/
  235. /* start:exit_sys()*/
  236. int exit_sys()
  237. {
  238. close(sockfd);
  239. close(mainfd);
  240. close(user_list_fd);
  241. printf("exit system");
  242. kill(0, SIGABRT);
  243. exit(0);
  244. }
  245. /* end:exit_sys()*/
  246. /* start:chat_history*/
  247. int get_page_size()
  248. {
  249. struct chat_history page_size_reader;
  250. i_lseek(mainfd, -HSTR_LEN, SEEK_END);
  251. i_read(mainfd, &page_size_reader, HSTR_LEN);
  252. return(page_size_reader.count);
  253. }
  254. int read_chat_history()
  255. {
  256. printf("****char*history***");
  257. printf("(n-nextpage; p-prepage; q-quit)\n");
  258. int page_num;/* */
  259. int remains;
  260. int berry = get_page_size();
  261. page_num = berry / 8;
  262. remains = berry % 8;
  263. if (remains != 0)
  264. page_num ++;
  265. else
  266. page_num = page_num;
  267. printf("there are %d page total %d items",
  268. page_num, berry);
  269. int i = -1;
  270. while (1)
  271. {
  272. char flag;
  273. if ((berry + i*8) >= 0)
  274. {
  275. printf("(%d~%d)\n", (berry + i*8), (berry + (i+1)*8));
  276. i_print_history(PRT_LEN, i);
  277. printf("@@@\n");
  278. while ('\n' == (flag = getchar()))
  279. {
  280. }
  281. switch (flag)
  282. {
  283. case 'p' :
  284. i--;
  285. break;
  286. case 'n' :
  287. i++;
  288. break;
  289. case 'q' :
  290. return(0);
  291. default :
  292. break;
  293. }
  294. if (i >= 0)
  295. {
  296. printf("have at the end!\n");
  297. printf("return to menu!\n");
  298. }
  299. }
  300. else
  301. {
  302. printf("(1~%d)\n", remains);
  303. i_print_history(remains, 0);
  304. printf("#########over##############\n");
  305. return(0);
  306. }
  307. }
  308. return(0);
  309. }
  310. /* end:chat_history*/
  311. /* start:menu*/
  312. int menu()
  313. {
  314. sleep(1);
  315. printf("----------help----menu---------\n");
  316. printf("\t r--report to user\n");
  317. printf("\t c--chat history\n");
  318. printf("\t h--help menu\n");
  319. printf("\t e--exit the system\n");
  320. printf("----------help_menu---------\n");
  321. int command = 0;
  322. printf("input command>");
  323. command = getchar();
  324. switch(command)
  325. {
  326. case 'c':
  327. read_chat_history();
  328. break;
  329. case 'e':
  330. exit_sys();
  331. break;
  332. case 'r':
  333. //report();
  334. //break;
  335. default :
  336. menu();
  337. break;
  338. }
  339. getchar();
  340. return(0);
  341. }
  342. /* end:menu*/
  343. int main()
  344. {
  345. init();
  346. pid_t pid;
  347. switch (pid = fork())
  348. {
  349. case -1 :
  350. perror("fork error\n");
  351. exit(1);
  352. break;
  353. case 0 :
  354. msg_cntl();
  355. break;
  356. default :
  357. menu();
  358. break;
  359. }
  360. return(0);
  361. }
复制代码


回复

使用道具 举报