首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux下的一个简单的多人聊天室

2012-11-08 
linux上的一个简单的多人聊天室/* *i.h is a used for creating a library *for server client *Mar 18 20

linux上的一个简单的多人聊天室

/* *i.h is a used for creating a library *for server client *Mar 18 2010 * */#ifndef _I_H#define _I_H#include <math.h>#include <stdio.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <inttypes.h>#include <time.h>#include <sys/ioctl.h> #include <net/if.h>#include <signal.h>#include <ncurses.h>#include <math.h>#define SEVR_IP     "127.0.0.1"#define SEVR_PORT   8081#define CNTNT_LEN   150#define MSG_LEN     sizeof(struct msg)#define ADDR_LEN    sizeof(struct sockaddr)#define USR_LEN     sizeof(struct user)#define PRT_LEN     8#define HSTR_LEN    sizeof(struct chat_history)/* declare Global variables */int mainfd;/* used as chat histroy file handle*/int sockfd;/* used as socket local handle */int count;struct sockaddr_in server;/* msg is used for communicating message */struct msg{int flag; /* flag meaning:1,ordinary; 2,log msg; 3,reg msg, other,file*/int id_from;int id_to;char content[CNTNT_LEN];char append[10]; };/* user is used information list */struct user{int id;char name[10];char password[10];char *p_chatlog;struct sockaddr user_addr;};/* chat_history used for reading chat history */struct chat_history{char content[CNTNT_LEN];char time[25];int to;int from;int count;};/* i_functions below is funtions needed by both client and sever */extern int i_saveto_chat(struct msg *pmsg);int i_clean_stdin (){while ('\n' == getchar()){continue;}return(0);}int i_print(char *pmsg, int size){int i = 1;for (i; i<= size; i++){if (*pmsg != '\n'){printf("%c", *pmsg);pmsg ++;}else {return(0);}}return(0);}int i_input(char *p_input){char c = '\0';int i;for (i = 0; i < CNTNT_LEN; i++){p_input[i] = getchar();if (p_input[i] =='\n'){return(0);}}printf("you have input long enough!\n");return(0);}int i_socket(int domain, int type, int protocol){int fd;if ((fd = socket(domain, type, protocol)) == -1){perror("creat socket error:");exit(1);}return(fd);}int i_bind(int fd, const struct sockaddr *addr, int namelen){if (-1 == bind(fd, addr, namelen)){perror("i_bind error:");exit(1);}return (0);}int i_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, int *size){if (-1 == recvfrom(fd, buf, len, flags, addr, size)){perror("i_recvfrom error:");exit(1);}return(0);}int i_sendto(int fd, void *buf, size_t len, int flags,struct sockaddr *addr, int size){if (-1 == sendto(fd, buf, len, flags, addr, size)){perror("i_sendto error");exit(1);}return (0);}int i_open(const char *pathname, int flags){int fd;if ((fd = open(pathname, flags)) == -1){perror("open_failed");exit(1);}return (fd);}int i_read(int fd, void *msg, int len){if(-1 == read(fd, msg, len)){perror("i_read error");exit(1);}return(0);}int i_write(int fd, void *msg, int len){if (-1 == write(fd, msg, len)){perror("i_write error");exit(0);}return(0);}/* init a socket,file and server addr */int i_init(){mainfd = i_open("./chat_log", O_RDWR|O_CREAT);sockfd = i_socket(AF_INET, SOCK_DGRAM, 0);/* initialize server address */bzero(&server, sizeof(server));server.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);server.sin_port = htons(SEVR_PORT);perror("init");return (0);}char *i_get_time(){time_t time_now;time(&time_now);return(ctime(&time_now));}int i_lseek(int fd, off_t size, int position){if (-1 == lseek(fd, size, position)){perror("seek error");exit(1);}return(0);}int i_saveto_chat(struct msg *pmsg){struct chat_history hstr;bzero(&hstr, HSTR_LEN);count = count + 1;hstr.count =count;hstr.from = pmsg->id_from;hstr.to = pmsg->id_to;strncpy(hstr.content, pmsg->content, CNTNT_LEN);strncpy(hstr.time, i_get_time(), 25);i_lseek(mainfd, 0, SEEK_END);i_write(mainfd, &hstr, HSTR_LEN);return(0);}int i_print_history(int len, int i){struct chat_history chat_reader;int j;int position;bzero(&chat_reader, HSTR_LEN);if (i != 0){position = len*i*HSTR_LEN;i_lseek(mainfd, position, SEEK_END);}else{position = len*i*HSTR_LEN;i_lseek(mainfd, HSTR_LEN, SEEK_SET);}for (j = 1; j <= len; j++){i_read(mainfd, &chat_reader, HSTR_LEN);printf("\n#item%d:id%dto id%d \n", j,chat_reader.from, chat_reader.to);i_print(chat_reader.content, CNTNT_LEN);printf("\n  Time:%s\n", chat_reader.time);}return(0);}#endif
/* *title:server.c *content:server part *start time: Mar.25.2011 *end time:  Apr.8 2011 */#include "i.h"int user_list_fd;/* start:initialization */int init(){i_init();user_list_fd = i_open("./user_list", O_RDWR|O_CREAT);struct user usr;/* init the user list file's fist user to 0*/memset((struct user*)&usr, '\0', sizeof(struct user));i_lseek(user_list_fd, 0, SEEK_SET);i_write(user_list_fd, (char*)&usr, USR_LEN);/* bind the struct sockaddr_in server to the sockfd */i_bind(sockfd, (struct sockaddr*)&server, ADDR_LEN);struct chat_history apple;bzero(&apple, HSTR_LEN);i_lseek(mainfd, 0, SEEK_SET);i_write(mainfd, &apple, HSTR_LEN);i_lseek(mainfd, -HSTR_LEN, SEEK_END);i_read(mainfd, &apple, HSTR_LEN);count = apple.count;return(0);}/* end:initialization *//* start:message control */int send_msg(struct msg *msg_recv, struct sockaddr *addr){int i;struct user usr;/* a common message come */printf("a ordinar message come !\n");i = msg_recv->id_to;i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);i_read(user_list_fd, &usr, USR_LEN);strncpy(msg_recv->append, usr.name, 10);i_sendto(sockfd, msg_recv, MSG_LEN, 0,&(usr.user_addr), ADDR_LEN);printf("id%d send a message to id%d sucess!\n", msg_recv->id_from, msg_recv->id_to);return(0);}int check_login(struct msg *msg_recv, struct sockaddr *addr){int i = msg_recv->id_from;;struct user usr;/* a login requet */printf("a login request come!\n");/* get the id's information */i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);i_read(user_list_fd, &usr, USR_LEN);int n;n = strcmp(usr.password, msg_recv->content);/* 如果验证成功,则发送成功信息 */if (n == 0){/* save user new address */i_lseek(user_list_fd, -USR_LEN, SEEK_CUR);usr.user_addr = *addr;i_write(user_list_fd, &usr, USR_LEN);/* tell user pass */i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,&(usr.user_addr), ADDR_LEN);}else{/* 出错的话的respond */if (0 != n){printf("id %d login error.\n", i);bzero(msg_recv->content, CNTNT_LEN);msg_recv->flag = -1;i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,&(usr.user_addr), ADDR_LEN);}return(1);}printf("Id %d login sucess!\n", i);return(0);}int reg_user(struct msg *msg_recv, struct sockaddr *addr){struct user usr;printf("a regit requet come:\n");/* find the last user and hava the please to add a new user */int n;i_lseek(user_list_fd, -USR_LEN, SEEK_END);i_read(user_list_fd, &usr, USR_LEN);/* 把新用户的信息赋值到usr然后填入到user list file中 */const char *name;const char *password;name = &(msg_recv->content[0]);password = &(msg_recv->content[10]);strcpy((usr.name), name);strcpy(usr.password, password);memcpy(&(usr.user_addr),addr, ADDR_LEN);usr.id = (usr.id + 1);i_lseek(user_list_fd, 0, SEEK_END);i_write(user_list_fd, &usr, USR_LEN);msg_recv->id_from = usr.id;/* regist to the user list then tell the user reg success */i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,addr, ADDR_LEN); printf("Id %d regist sucess!\n", usr.id);return(0);}int msg_cntl(){struct msg msg_recv;struct sockaddr addr_recv;printf("begin listen input...\n");int size = ADDR_LEN;for (;;){bzero(&msg_recv, MSG_LEN);i_recvfrom(sockfd, &msg_recv, sizeof(struct msg), 0,&addr_recv, &size);printf("message received...\n");i_saveto_chat(&msg_recv);switch (msg_recv.flag){case 1 :send_msg(&msg_recv,(struct sockaddr*)&addr_recv);/* send ordinary chat */break;case 2 :check_login(&msg_recv, (struct sockaddr*)&addr_recv);break;case 3 :reg_user(&msg_recv, (struct sockaddr*)&addr_recv);break;default :break;}}return(0);}/* end:message control*//* start:exit_sys()*/int exit_sys(){close(sockfd);close(mainfd);close(user_list_fd);printf("exit system");kill(0, SIGABRT);exit(0);}/* end:exit_sys()*//* start:chat_history*/int get_page_size(){struct chat_history page_size_reader;i_lseek(mainfd, -HSTR_LEN, SEEK_END);i_read(mainfd, &page_size_reader, HSTR_LEN);return(page_size_reader.count);}int read_chat_history(){printf("****char*history***");printf("(n-nextpage; p-prepage; q-quit)\n");int page_num;/* */int remains;int berry = get_page_size();page_num = berry / 8;remains = berry % 8;if (remains != 0)page_num ++;elsepage_num = page_num;printf("there are %d page total %d items", page_num, berry);int i = -1;while (1){char flag;if ((berry + i*8) >= 0){printf("(%d~%d)\n", (berry + i*8), (berry + (i+1)*8));i_print_history(PRT_LEN, i);printf("@@@\n");while ('\n' == (flag = getchar())){}switch (flag){case 'p' :i--;break;case 'n' :i++;break;case 'q' :return(0);default  :break;}if (i >= 0){printf("have at the end!\n");printf("return to menu!\n");}}else {printf("(1~%d)\n", remains);i_print_history(remains, 0);printf("#########over##############\n");return(0);}}return(0);}/* end:chat_history*//* start:menu*/int menu(){sleep(1);printf("----------help----menu---------\n");printf("\t r--report to user\n");printf("\t c--chat history\n");printf("\t h--help menu\n");printf("\t e--exit the system\n");printf("----------help_menu---------\n");int command = 0;printf("input command>");command = getchar();switch(command){case 'c':read_chat_history();break;case 'e':exit_sys();break;case 'r'://report();//break;default :menu();break;}getchar();return(0);}/* end:menu*/int main(){init();pid_t pid;switch (pid = fork()){case -1 :perror("fork error\n");exit(1);break;case 0 :msg_cntl();break;default :menu();break;}return(0);}
/* *title: client.c *start_time: Mar.18 2011 *end_time:  Apr.8 2011 */#include "i.h"#define START_PORT 8089struct sockaddr_in my_addr;int my_id;int my_log();/* declare funtion*//* */int i_send_msg(){int id;struct msg the_msg;char end = '@';printf("input recver id:");scanf("%d", &id);getchar();printf("\ninput content:");i_input(the_msg.content);char flag = 'y';if (1){the_msg.flag = 1;the_msg.id_from = my_id;the_msg.id_to = id;i_sendto(sockfd, &the_msg, sizeof(struct msg), 0,(struct sockaddr*)&server, sizeof(struct sockaddr));i_saveto_chat(&the_msg); /* save to history */printf("send to id:%d success.\n", my_id);return(0);}elsereturn(1);return(0);}int reply(){return(0);}int send_file(){return(0);}/**//* start:initialize */int init(){struct ifreq req;struct sockaddr_in *host;int port;i_init();/* init user addr */bzero(&my_addr, sizeof(struct sockaddr));my_addr.sin_family = AF_INET;strcpy(req.ifr_name, "lo");if ( ioctl(sockfd, SIOCGIFADDR, &req) < 0 ) /* get local ip address */{perror("get local ip error");exit(1);        } host = (struct sockaddr_in*)&(req.ifr_addr);printf("ip: %s\n", inet_ntoa(host->sin_addr));memcpy(&my_addr, (struct sockaddr_in*)&(req.ifr_addr), sizeof(struct sockaddr_in));port = START_PORT;do {port++;my_addr.sin_port = htons(port);bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)); } while (errno == EADDRINUSE);struct chat_history apple;memset(&apple, 'b', HSTR_LEN);i_lseek(mainfd, 0, SEEK_SET);apple.count = 0;i_write(mainfd, &apple, HSTR_LEN);i_lseek(mainfd, -HSTR_LEN, SEEK_END);i_read(mainfd, &apple, HSTR_LEN);count = apple.count;  printf("port:%d\n", port);printf("init successful!!!\n");return(0);}/* end:initialize *//* start:chat_history*/int get_page_size(){struct chat_history page_size_reader;i_lseek(mainfd, -HSTR_LEN, SEEK_END);i_read(mainfd, &page_size_reader, HSTR_LEN);return(page_size_reader.count);}int read_chat_history(){printf("****char*history***");printf("(n-nextpage; p-prepage; q-quit)\n");int page_num;/* */int remains;int berry = get_page_size();page_num = berry / 8;remains = berry % 8;if (remains != 0)page_num ++;elsepage_num = page_num;printf("there are %d page total %d items", page_num, berry);int i = -1;while (1){char flag;if ((berry + i*8) >= 0){printf("(%d~%d)\n", (berry + i*8), (berry + (i+1)*8));i_print_history(PRT_LEN, i);printf("@@@\n");while ('\n' == (flag = getchar())){}switch (flag){case 'p' :i--;break;case 'n' :i++;break;case 'q' :return(0);default  :break;}if (i >= 0){printf("have at the end!\n");printf("return to menu!\n");}}else {printf("(1~%d)\n", remains);i_print_history(remains, 0);printf("#########over##############\n");return(0);}}return(0);}/* end:chat_history*//* start:exit_sys*/void exit_sys(){close(sockfd);close(mainfd);kill(0, SIGABRT);exit(0);}/* end:exit_sys*//* start:menu*/int print_menu(){printf("\n--------------help--menu----------------\n");printf("\t h--help munu\n");printf("\t s--send message\n");printf("\t r--reply to\n");printf("\t c--chat history\n");printf("\t f--send files\n");printf("\t e--exit the system\n");printf("----------------help--menu----------------\n");}int get_input(char *command){printf(">");scanf("%c", command);return(1);}int menu(){/* to avoid the output at mixed with the sub process */sleep(1);print_menu();char command;while (1 == get_input(&command)){switch(command){case 'h':print_menu();break;case 's':i_send_msg();break;case 'r':reply();break;case 'f':send_file();break;case 'c':read_chat_history();break;case 'e':exit_sys();break;default :printf(">");break;}}return(0);}/* end:menu*//* start:message contol :send_msg and recv_msg */int ordnary_msg_recv(struct msg *pmsg){char time_info[25];char end_symble;end_symble = '&';/* handle the msg */printf("Message:from %s(id%d) to U:\n", pmsg->append, pmsg->id_from);i_print(pmsg->content, MSG_LEN);printf("\n\t%s", i_get_time());return(0);}int file_msg_recv(struct msg *pmsg){}int handle_msg(struct msg *pmsg){if (pmsg->flag == 1){ordnary_msg_recv(pmsg);return(0);}else if (pmsg->flag >= 4){file_msg_recv(pmsg);return(0);}return(0);}int listen_msg(){struct msg msg_recv;struct sockaddr addr_recv;int len = ADDR_LEN;printf("begin listen...\n");for ( ; ; ){i_recvfrom(sockfd, &msg_recv, MSG_LEN, 0,  &addr_recv, &len);i_saveto_chat(&msg_recv); /* save to history */ ordnary_msg_recv(&msg_recv);}}/* end:message contol*//* start:log process :login and regist */int login(){/* input id:*/printf("*****login>>\n");printf("id:");scanf("%d", &my_id);/* input password*/char password[15];printf("\npassword(*less 15 char):");scanf("%s", password);getchar();/* send login information */struct msg log_msg;bzero(&log_msg, MSG_LEN);log_msg.flag = 2;log_msg.id_from = my_id;log_msg.id_to = 0;strncpy(log_msg.content, password, 15);i_saveto_chat(&log_msg); /* save to history */i_sendto(sockfd, (struct msg*)&log_msg, MSG_LEN, 0, (struct sockaddr*)&server, sizeof(struct sockaddr));//printf("log_msg : %d\n", log_msg.id_from);//printf("password: %s\n", log_msg.content);/* after input msg ,wait for server respond*/struct sockaddr in_addr;int len = ADDR_LEN;i_recvfrom(sockfd, (struct msg*)&log_msg, MSG_LEN,0,&in_addr, &len);if (2 == log_msg.flag){printf("login success\n");return(0);}else{printf("login error:%s\n", log_msg.content);printf("please relog..\n");menu();}return (0);}int regist(){printf("*****regist>>\n");/* input chat name */char name[10];bzero(name, 10);printf("input your chat name(less 8 char):");scanf("%s", name);//name[9] = ';';         /* add a ; symbol in the end of name *//* input password */char password[15];bzero(password, 15);printf("\ninput your password(less 14 char):");scanf("%s", password);/* send regist information*/struct msg reg_msg;bzero(&reg_msg, MSG_LEN);reg_msg.flag = 3;reg_msg.id_from = 0;reg_msg.id_to = 0;bzero(reg_msg.content, CNTNT_LEN);strncpy(reg_msg.content, name, 10);strncpy(&(reg_msg.content[10]), password, 15);reg_msg.content[25] = '\n';i_saveto_chat(&reg_msg); /* save to history *//* send regist informatin to server */i_sendto(sockfd, (struct msg*)&reg_msg, sizeof(struct msg), 0, (struct sockaddr*)&server, ADDR_LEN);/* after input msg ,wait for server respond*/printf("wating for server reply...\n");struct sockaddr in_addr;struct msg msg_back;int len = ADDR_LEN;bzero(&in_addr, ADDR_LEN);bzero(&msg_back, MSG_LEN);i_recvfrom(sockfd,(struct msg*)&msg_back, MSG_LEN,0,&in_addr, &len);/* check whether pass */if (3 != msg_back.flag){printf("error: %s \n", msg_back.content);exit(1);}elsemy_id = msg_back.id_to;printf("congratulate! you have regist" "id %s(id %d) success\n", msg_back.content, msg_back.id_to);login();return(0);}int my_log(){/* choose login or regist*/char flag;printf("are you want login or regist(l/r)\n");scanf("%c", &flag);getchar();switch (flag){case 'l' :login();break;case 'r' :regist();break;default :printf("error input\n");my_log();break;}return (0);}/* end:log */int main(){init();printf("\n************welcome!************\n");my_log();pid_t pid;switch (pid = fork()){case -1 :perror("fork error!\n");exit(1);break;case 0 :listen_msg();break;default :menu();break;}}

热点排行