C语言开发邮件系统-2

基本功能设定:申请、注销、发送、阅读、删除、保存;
服务器:保存信息、验证密码、接收转发、管理(存、开、删);
客户端:选择服务项、读删编辑发送;
共有功能:C到S发送请求、密码等;S到C发送响应;C到S发送邮件;S到C传送邮件。(可用Linux的SOCKET网络编程接口实现)
模块:
    1、服务器:文件与通信;(信件管理的开删等与用户信息的保持验证)
    2、客户端:通信与界面。(界面功能与传邮件及请求信息)
服务端:
  文件处理模块:
      1、用户信息文件一个;(集中用户文档)
      2、邮件列表文件若干;(记录寄信人、邮编号、发信时间、主题等)
      3、邮件文件若干;(保存用户邮件内容)
  信件管理模块:打开删功能,一个函数实现;
      1、打开邮件列表;(登录成功调用该功能)
      2、打开邮件;(读邮件时调用)
      3、删除邮件;(删除命令调用)
  用户信息管理模块:
      1、保持用户密码对;(点注册传送信息时调用,并添加到邮件文件) 
      2、验证密码;(登录发送密码时调用,成功则法提示到C并打开邮件列表,失败提示重新输入密码)
  服务器通信模块:调用SOCKET函数族,创建套接字、绑定端口、等待连接。
      1、S→C发送响应;
      2、S→C发送邮件;(S打开邮件文件,传输文本,C接收并写入本地新文件);
      3、C→S发送服务请求;
      4、C→S传送邮件;(同上,将S与C对调)
客户端:
  界面模块:
      1、系统初始界面;(包括"注册"、"登录")
      2、输入账号密码界面;(点击上面进入)
      3、进入邮箱界面;(打开邮件列表,提供读发删退注销等命令选择)
      4、邮件编辑界面;(点"发邮件"进入,)
      5、读邮件界面。 (选择"读邮件",S将邮件→C)
  通信模块:
      1、调用SOCKET函数族;(需知道服务器工作的端口)

详细设计:
   1、代码组织:
        服务器程序:主程序、通信模块与文件处理模块;(前两者在同一文件,组成服务器程序serprog.c,后者由include引用)
        客户端程序:放在cliprog.c(缺乏文件处理模块)
   2、数据格式:
        抽象数据结构邮件结构类型,包括收发者、主题、正文、时间、编号等。
   3、同步机制:
        同步函数:int SendSockChar(int sockfd,char ch):发送同步字符。参数,套接字号及待发送字符;
                  char GetSockChar(int sockfd):接收一个同步字符。读取用while循环
   4、系统函数:
         read();
         write();
   5、自编函数:
         int readline(int,void*,int);从套接字中读取一行内容
         int sockendline(int);发送换行符
         void CutEndl(char *str);去换行符(避免验证密码返回错误结果)
   6、头文件和常量定义:
   7、主程序:      
        服务器主程序:并发服务器
            1、初始化地址信息;
            2、创建套接字开始倾听; 
            3、等待连接。
          (若S进程接收一个连接,系统调用FORK创建一个子进程为客户服务,父进程继续在端口上等待连接;)
        客户端主程序:
            1、main()函数:命令行参数3个,传入服务器程序运行IP地址和端口号,验证后建立连接,
                           调用客户端服务的主函数。(不太明白运行机制) 
   8、连接函数:
         1、服务器:StartListening(),调用socket()、bind()、listen()建立倾听套接字;
         2、客户端:ConnectToServer(),调用socket()、connect()建立与服务器连接,参数为服务器IP及端口号,
                    调用时输入命令行参数agrv[1]和agrv[2]。   
   9、服务“主函数”:
         1、服务器主函数 int ServerMain(int sockfd)
         2、客户端主函数 int ClientMain(int sockfd)
   10、邮件服务函数:
        A、服务器服务函数:
          1、int RegisterSev(int sockfd); //注册功能服务器端函数
          2、int RecvUsrPswd(int sockfd,char *Usr,char *Pswd); //接收用户密码
          3、int LoginSev(int sockfd); //登录功能服务器端函数
          4、int MailService(int sockfd,char *Usr); //进入信箱后邮件服务服务器端函数
          5、int SendMaillist(list sockfd,char *Usr); //发送邮件列表服务器端函数
          6、int ReadMailSev(int sockfd); //阅读邮件功能
          7、int DelMailSev(int sockfd,char *Usr); //删除
          8、int SendMailSev(int sockfd,char *Usr);
        B、客户端服务函数:
          1、int RegisterCli(int sockfd); //注册功能客户端端函数
          2、int SendUsrPswd(int sockfd,char *Usr,char *Pswd); //发送用户密码
          3、int LoginCli(int sockfd); //登录功能客户端函数
          4、int MailClient(int sockfd); //登录成功邮件服务客户端函数
          5、int ReadMailCli(int sockfd); //阅读邮件功能
          6、int DelMailCli(int sockfd); //删除
          7、int SendMailCli(int sockfd); //发邮件
    11、流程图:服务端与客户端

C语言开发邮件系统-2_第1张图片

C语言开发邮件系统-2_第2张图片

C语言开发邮件系统-2_第3张图片

C语言开发邮件系统-2_第4张图片

    12、文件处理模块接口函数:
          1、mail.h和usrpass.h头文件;(包含服务器邮件处理模块与用户信息管理模块)
          2、6个接口函数:
                 a、int UsrStore(char *Usr,char *Pswd); //保存用户密码对
                 b、int TestPasd(char *Usr,char *Pswd); //验证密码
                 c、int getmsgfrmdb(char *Usr); //形成邮件列表临时文件
                 d、int StoreMail(MailStruct *Mail) //保存邮件 参数为邮件结构类型邮件
                 e、int GetMail(int mail_no,char *buf); //取邮件 参数为整型邮件代号和字符串缓冲区
                 f、int DelMail(int mail_no,char *Usr); //删除邮件

补充说明:
    1、程序编译和启动:
         a、服务器程序sevproc.c与文件处理模块.c文件与.h在同一目录;
         b、shell下输入: gcc *.c -o sevprog  得到可执行文件sevprog;
         c、shell下输入:./sevprog 启动服务器程序;
         d、客户端程序cliprog.c在另一目录;
         e、shell下输入:gcc cliprog.c -o cliprog 得到可执行文件cliprog;
         f、在另一个虚拟终端输入:./cliprog 127.0.0.1 5500 启动客户程序;//地址与端口号
    2、运行状态:
         

附录:
 服务器程序和客户端程序的源代码
/*sevprog.c*/

#include
#include  
#include  
#include  
#include  
#include  
#include  
#include  

#include"mail.h"
#include"usrpass.h"

#define MAXSIZE 500
#define MYPORT 5500  
#define BACKLOG 10  
#define OK 1     

typedef struct 
  {
    int mail_num;
    char to[MAXSIZE];
    char from[MAXSIZE];
    char subject[MAXSIZE];
    char content[MAXSIZE];
    time_t recvtime;
   }MailStruct;

int ServerMain();

char GetSockChar(int);
int SendSockChar(int,char);
int readline(int,void*,int);
int sockendline(int);
void CutEnd(char *str);

int RegisterSev(int);
int RecvUsrPswd(int,char*,char*);
int LoginSev(int);

int MailService(int,char*);
int SendMailList(int,char*);

int ReadMailSev(int sockfd);
int DelMailSev(int  sockfd,char *Usr);
int SendMailSev(int sockfd,char *Usr);

int main()
 {
   int sockfd,new_fd;
   struct sockaddr_in their_addr;
   int sin_size;

   sockfd=StartListening();
   
   while(1)
    {
      sin_size=sizeof(struct sockaddr_in);
      new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);
      if(new_fd==-1){
         perror("accept");
         exit(1);         
        }
      printf("server.got connection from %s",inet_ntoa(their_addr.sin_addr));
      if(!fork()){
         ServerMain(new_fd);
         close(new_fd);
        }
     close(new_fd);
     }
   while(waitpid(-1,NULL,WHOHANG>0));
 }

 int  /*read a text line from a descriptor*/
 readline(int fd,void *vptr,int maxlen)
  {
    int n,rc;
    char c,*ptr;
    
    ptr=vptr;
    for(n=1;nfrom,Usr);
     strcpy(TemMail->content,Usr);
     strcat(TemMail->content,"\n");

     ch=GetSockChar(sockfd);
                   
     readline(sockfd,buf,MAXSIZE);
     CutEnd(buf);
     strcpy(TempMail->to,buf);
     strcpy(TemMail->content,buf);
     strcat(TemMail->content,"\n");

     readline(sockfd,buf,MAXSIZE);
     CutEnd(buf);
     strcpy(TempMail->subject,buf);
     strcpy(TemMail->content,buf);
     strcat(TemMail->content,"\n");

     read(sockfd,&ch,1);
     i=0;
     while(ch!=0)
       {
         buf[i++]=ch;
         read(sockfd,&ch,1);
       }
     buf[i]='\0';
        
     strcat(TemMail->content,buf);
     strcat(TemMail->content,"\n");

     TempMail->recvtime=time(time_t*)NULL);
    
     MailToStore=(struct message*)malloc(sizeof(struct message));
     MailToStore->to=TempMail->to;
     MailToStore->from=TempMail->from;
     MailToStore->recvtime=TemMail->recvtime;
     MailToStore->sendtime=TempMail->recvtime;    
     MailToStore->subject=TempMail->subject;
     MailToStore->content=TempMail->content;
     sprintf(buf,"%d",(int)MailToStore->recvtime);
     MailToStore->messageid=buf;

     printf("MailToStore->content=\n%s\n",MailToStore->content);

     StoreMail(MailToStore);
     SendStoreChar(sockfd,'D');
     ch=GetSockChar(sockfd);
     if(ch=='D')
       return OK;
     else
       return -1;
    }
/*---------------------------------------------------------------------*/    

/*cliprog.c*/     
 
#include
#include  
#include  
#include  //function atoi()
#include 
#include 
#include  //function char* getpass(const char*)
#include  
#include  
#include  

#define MAXSIZE 500
#define OK 1  

typedef struct
  {
    int mailnum;
    char to[MAXSIZE];
    char from[MAXSIZE];
    char subject[MAXSIZE];
    char content[MAXSIZE];
   }MailStruct;

/*
  Signals meaning:
  B:Begin,D:Done,T:True,F:False
*/

int ConnectToServer(char*,char*);
int ClientMain(int);

char InterfaceA();
int SendSockChar(int,char);
char GetSockChar(int);
int sockendline();
void CutEndl(char*str);
int readline(int,void*,int);

void InputUsrPswdR(char*,char*);
void InputUsrPswdL(char*,char*);
int SendUsrPswd(int,char*,char*);
int RegisterCli(int);
int MailClient(int);

int ReadMailCli(int);
int DelMailCli(int);
int SendMailCli(int);

int main(int argc,char **argv)
 {
   int sockfd;

   if(argc!=3)
     {
       fprintf(stderr,"usage:./cliprog\n");
       exit(1);
      }

    sockfd=ConnectToServer(argv[1],argv[2]);
    ClientMain(sockfd);
    close(sockfd);
    printf("......local socket close\n");
    return 0;
  }

 int ConnectToServer(char *IpAddr,char *SerPort)  //连接服务
   {
     int sockfd;
     struct sockaddr_in servaddr;
     sockfd=socket(AF_INET,SOCK_STREAM,0);
     bzero(&servaddr,sizeof(struct sockaddr_in));
     servaddr.sin_family=AF_INET;
     servaddr.sin_port=htons(atoi(SevPort));
     inet_aton(IpAddr,&servaddr.sin_addr);
     connect(sockfd,(struct sockaddr*)&seraddr,sizeof(struct sockaddr));
     return sockfd;
    }

 int ClientMain(int sockfd)
  {
    char Comch,Infch;
    char recvbuf[MAXSIZE],sendbuf[MAXSIZE];
    
    Comch=InterfaceA();
    SendSockChar(sockfd,Comch);
    switch(Comch)
      {
        case 'R':
            RegisterCli(sockfd);
            break;
        case 'L':
            LoginCli(sockfd);
            break;
       }
   }
 
 int SendSockChar(int sockfd,char ch) //发送 send a signal char or a command char to server through socket
   {
     return write(sockfd,&ch,1);
    }

 char GetSockChar(int sockfd) //接收 get a command char or a signal char from socket
    {
      char ch;
      while((read(sockfd,&ch,1))==0);
      return ch;
    }

 char InterfaceA()  //接口
  {
    char ch;
    printf("\n\n Welcome to DTMail system!\n");
    printf("Version 1.0,Written by Shawn");
    printf("Supervisor:Shawn");
    printf("Octber 28,2016 \n");
    printf("\n Please input your choice:R or L?\n");
    printf("[R]egesiter\n");
    printf("[L]ogin\n");
    do {
          ch=getchar();
          ch=toupper(ch);
          if(ch!='R'&&ch!='L')
            printf("No such choice,please enter again,R or L:");
    }while(ch!='R'&&ch!='L');
    return ch;
  }

 int RegisterCli(int sockfd)  //客户端注册
   {
     char ch;
     char Username[MAXSIZE],Password[MAXSIZE];
     InputUsrPswdR(Usrname,Password);
     SendUsrPswd(sockfd,Usrname,Password);
     if((ch=GetSockChar(sockfd)=='D'))
        printf("Register Successfully!\n");
     return OK;
    } 

 int LoginCli(int sockfd)  //登录
  {
     char ch;
     char Username[MAXSIZE],Password[MAXSIZE];
     do{
         char ret;
         char InputUsrPswdL(Usrname,Password);
         SendUsrPswd(sockfd,Usrname,Password);
         while(read(sockfd,&ret,1)==0);
         if(ret=='T')
             MailClient(sockfd);
         else
             printf("Password wrong,please input again\n");
     }while(ret=='F');
      return OK;
   }

 void InputUsrPswdL(char *Usr,char *Pswd);
   {
     char *ptr;
     puts("please input usrname:");
     scanf("%s",Usr);
     ptr=getpass("please input password:");
     strcpy(Pswd,ptr);
   }

  void InputUsrPswdR(char *Usr,char *Pswd);
   {
      char passwd[20];
      char *ptr1,*ptr2;
      int ret;
      printf("username?");
      scanf("%s",Usr);
      do{
           ptr1=getpass("Input password:");
           strcpy(Pswd,ptr1);
           ptr2=getpass("Retype password:");
           if((ret=strcmp(ptr2,Pswd))==0)
              printf("password accepted!\n");
           else
              printf("two passwords do not match,input again.\n");
       }while(ret!=0);
    }
              
 int SendUsrPswd(int sockfd,char *Usr,char *Pswd)  //发送用户名及密码
   {
     int usrlen,pswlen;
     int ret1,ret2;
     usrlen=strlen(Usr);
     SendSockChar(sockfd,'B');
     pswlen=strlen(Pswd);
     ret1=write(sockfd,Usr,usrlen);
     sockenline(sockfd);
     ret2=write(sockfd,Pswd,pswlen);
     sockenline(sockfd);
     if(ret1==usrlen && ret2==pswlen)
          return 0;
     else 
          return -1;
    }

 int MailClient(int sockfd)  //客户端邮件
   {
     char ch;
     printf(Login Successfully!\n);

     RecvMailList(sockfd);
     printf("\n Please input your choice:\n");
     for(;;)
       {
          printf("[R]ead mail \n");
          printf("[D]elet mail \n");
          printf("[S]end mail \n");
          printf("[E]xit \n");
          do{
               ch=getchar();
           }while(!isalpha(ch));
          ch=toupper(ch);
          SendSockChar(sockfd,ch);
          printf("input command:%c\n",ch);
          switch(ch)
             {
               case 'R':
                    ReadMailCli(sockfd);
                    break;
               case 'D':
                    DelMailCli(sockfd);
                    break;
               case 'S':
                    SendMailCli(sockfd);
                    break;
               case 'E':
                    printf("exit the mail system,byebye!");
                    return OK;
               default:
                    printf("No such command,input again.\n");
               }
               printf("\n Another sevice? Please input your choice:\n");
         }
        printf("\n sevice completed,bye!\n");
        return OK;
   }

  int RecvMaliList(int sockfd)  //邮箱列表
    {
      int i;
      char ch,buf[MAXSIZE];
      ch=GetSockChar(sockfd);
      i=0;
      while(ch!=0)
        {
         buf[i++]=ch;
         read(sockfd,&ch,1);
       }
      buf[i]=0; //为何是0,或是错误?
      printf("%s \n",buf);
    }

 int sockendline(int sockfd)
   {
     const char ch='\n';
     if(write(sockfd,&ch,1)==1)
       return 0;
     else
       -1;//不用return吗?
    }

  int CutEndl(char *str)
   {
     int len;
     len=strlen(str);
     if(str[len-1]=='\n')
        str[len-1]='\0';
    }
    
  int readline(int fd,void *vptr,int maxlen)
    {
      int n,rc;
      char c,*ptr;
    
      ptr=vptr;
      for(n=1;n



你可能感兴趣的:(C语言案例)