简单实现linux聊天室程序

花了很长时间用来练习掌握linux上socket的一个聊天室程序,可以实现的哦。
具体代码如下

代码一:

  #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 = '';    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:%sn", chat_reader.time);    }       return(0);  }     #endif

代码二:

  #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, '', 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 ++;    else      page_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 usern");    printf("t c--chat historyn");    printf("t h--help menun");    printf("t e--exit the systemn");    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 errorn");        exit(1);        break;      case 0 :        msg_cntl();        break;      default :        menu();        break;    }       return(0);  }

代码三:

  #include "i.h"     #define START_PORT 8089     struct 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);    }    else      return(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: %sn", 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:%dn", 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 ++;    else      page_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 munun");    printf("t s--send messagen");    printf("t r--reply ton");    printf("t c--chat historyn");    printf("t f--send filesn");    printf("t e--exit the systemn");    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("nt%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 : %dn", log_msg.id_from);  //printf("password: %sn", 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 successn");      return(0);    }      else    {      printf("login error:%sn", 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(®_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(®_msg); /* save to history */       /* send regist informatin to server */    i_sendto(sockfd, (struct msg*)®_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);    }    else      my_id = msg_back.id_to;      printf("congratulate! you have regist"        "id %s(id %d) successn", 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 inputn");        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;    }  }

希望本文所述对大家实现linux多人聊天室程序。

参与评论