• select多用户之间通信



    查看记录:10/20  
    今天又重新看了一下程序,觉得ListenKeyboard这个函数写的很好。利用select监听键盘,成功的解决了
    必须输入才会刷新消息的问题。这样等待15秒后也可刷新消息,效果很好
     
    ----------------------------------修正之后第二版-----------------------------------------
     
    Record:    1.在第一版的基础上添加了登录以及注册的功能
                       登录与注册的功能依赖文件UserList实现。
                       默认的用户为admin, 密码为admin
                     2.添加了用select实现的自动刷新功能
                       当用户停留在输入选择界面超过15秒后,便会自动刷新
                       好处就是别人发送的信息用户可以在等待15秒后直接看到(利用select)
                     3.将部分功能迁移到了.h文件中,便于查看代码与修改
     
    -------------------------------------------------------------------------------------------------
     
    【具体代码】
     
    【server.c】
     
    /************************************
    Version:2.0
    Author:Shaw Song
    Program: server.c
    Content: 1.one server to offer many
             clients communicate server
             2.add the function of sign
             3.add the function of login
    Records: shaw song  10/08 morning
             shaw song  10/09 afternoon
    ************************************/
    #include "server.h"
     
    #define MAX_FD_NUM  100
    #define MyPort 8888
     
    int main()
    {
        int MaxFd=0;
        int ConnectAmount = 0;
        int ListenFd;
        int ClientFd;
        char Name[20];
        struct timeval tv;
        struct sockaddr_in ServerAddr, ClientAddr;
        fd_set FdSet;
        FdName fd_name_table[MAX_FD_NUM];
     
        //create ListenFd
        ListenFd = socket(AF_INET, SOCK_STREAM, 0);
        if (-1 == ListenFd)
        {
            perror("socket create error :");
            exit(1);
        }
     
        ServerAddr.sin_family = AF_INET;
        ServerAddr.sin_port = htons(MyPort);
        ServerAddr.sin_addr.s_addr = INADDR_ANY;
        if (bind(ListenFd, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) == -1)
        {
            perror("bind error:");
            exit(1);
        }
     
        if (listen(ListenFd, 10) == -1)
        {
            perror("listen error");
            exit(1);
        }
     
        //recv and send message
        //init
        MaxFd = ListenFd;
        int i;
     
        for (i = 0; i < MAX_FD_NUM; i++)
        {
            fd_name_table[i].fd = 0;
            memset(fd_name_table[i].name, '', 20);
        }
     
        while(1)
        {
            FILE* file;
            file = fopen("ChatRecord", "a+");
            if (file < 0)
            {
                perror("open CharRecord fail!");
                exit(1);
            }
            fseek(file, 0, SEEK_END);
            //select
            FD_ZERO(&FdSet);
            FD_SET(ListenFd, &FdSet);
            printf("-------------------------- ");
            printf("now online %d  clients: ",ConnectAmount);
            for(i = 0; i < MAX_FD_NUM; i++)
            {
                if(fd_name_table[i].fd != 0)
                {
                    printf("%s ",fd_name_table[i].name);
                    FD_SET(fd_name_table[i].fd, &FdSet);
                    if (fd_name_table[i].fd > MaxFd)
                    {
                        MaxFd = fd_name_table[i].fd;
                    }
                }
            }
     
            tv.tv_sec = 10;
            tv.tv_usec = 0;
            int ret;
            ret=select(MaxFd+1, &FdSet, NULL, NULL, &tv);
            if (ret < 0)
            {
                perror("select error");
                exit (1);
            }
            if (ret == 0)
            {
            //    printf("time out! ");
                continue;
            }
     
            //connect to new client
            if(FD_ISSET(ListenFd, &FdSet))
            {
     
                int sin_size=sizeof(ServerAddr);
                memset(Name, '', 20);
                ClientFd = accept(ListenFd, (struct sockaddr *)&ClientAddr, &sin_size);
                printf("ClientFd:%d ",ClientFd);
                if (ClientFd < 0)
                {
                    printf("can't accept a new ClientFd! ");
                    continue;
                }
                if (Server_Login(ClientFd, Name) == 0)
                    close(ClientFd);
                else
                {
                    for (i = 0; i < MAX_FD_NUM; i++)
                    {
                        if(fd_name_table[i].fd == 0)
                        {
                        fd_name_table[i].fd = ClientFd;
                        memcpy(fd_name_table[i].name, Name,20);
                        break;
                        }
                    }
                    ConnectAmount++;
                }
            }
     
            //recv and send
            for (i = 0; i < MAX_FD_NUM; i++)
            {
                if (FD_ISSET(fd_name_table[i].fd, &FdSet))
                {
     
                    char buffer[140];
                    memset(buffer, '', 140);
                    int recv_ret;
                    recv_ret = recv(fd_name_table[i].fd, buffer, sizeof(buffer), 0);
                    if (recv_ret <= 0)
                    {
                        printf("%s offline ",fd_name_table[i].name);
                        close(fd_name_table[i].fd);
                        fd_name_table[i].fd = 0;
                        memset(fd_name_table[i].name, '',20);
                        ConnectAmount--;
                        FD_CLR(fd_name_table[i].fd, &FdSet);
                        break;
                    }
                    //fputs(buffer,file);
                    //fputs(" ",file);
                    char SendName[20];
                    char DestName[20];
                    char SendMsg[100];
                    memset(SendName,'',20);
                    memset(DestName,'',20);
                    memset(SendMsg,'',100);
                    split_string(buffer, DestName, SendName, SendMsg);
     
                    printf("%s %s %s ",DestName,SendName, SendMsg);
                    int flag = 0;
                    int j = 0;
                    for (j = 0;j < MAX_FD_NUM; j++)
                    {
                        if (memcmp(DestName,fd_name_table[j].name,20) == 0)
                        {
                                int DestTemp = fd_name_table[j].fd;
                                  send(DestTemp, buffer, sizeof(buffer),0);
                                fputs(buffer,file);
                                fputs(" ",file);
                                flag=1;
                                break;
                        }
                        else if (memcmp(DestName, "SIGN", 4) == 0)
                        {
                            Server_Sign(SendName, SendMsg);
                            flag = 1;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        printf("can't find the %s! ",DestName);
                    }
                    else
                    {
                        printf("send to the %s success! ",DestName);
                    }
                }
            }
            fclose(file);
        }
     
    }
     
     
    【server.h】
     
     
    /************************************
    Version:2.0
    Author:Shaw Song
    Program: server.h
    Content: 1.one server to offer many
             clients communicate server
             2.add the function of sign
             3.add the function of login
    Records: shaw song  10/08 morning
             shaw song  10/09 afternoon
    ************************************/
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
     
    #define USERFILE "UserList"
     
    /**************************
    Name:FdName
    Function: relate the fd and
              Client name
    ***************************/
    typedef struct
    {
        int fd;
        char name[20];
    } FdName;
     
    /********************************
    Function Name:split_string
    Function:split the string buffer
             buffer:xxxxx#xxxx#xxxxx@
    Parameter: char* p is the buffer
               char* Dest Send Msg is
               the DestName SenderName
               and the Message Sended
    *********************************/
     
    void split_string(char* p, char* Dest, char *Send, char* Msg)
    {
        while(*p != '#')
            *Dest++ = *p++;
            p++;
        while(*p != '#')
            *Send++ = *p++;
            p++;
        while(*p != '@')
            *Msg++ = *p++;
    }
     
    /********************************
    Function Name:Server_Login
    Function:confirm the UserName and
             Passwd
    Parameter: ClientFd is the fd of
               the new Client
               username is the name of
               user
    Return: type:int
                 1 means Login Success
                 0 means Login Fail
    *********************************/
    int Server_Login(int ClientFd, char* username)
    {
        int ret;
        char RecvBuf[50];
        memset(RecvBuf, '', 50);
        ret = recv(ClientFd, RecvBuf, 50, 0);
        if (ret <= 0)
        {
            printf("Recv UserName and PassWord Fail! ");
            return 0;
        }
        //init Name
        char* p = NULL;
        p = RecvBuf;
        while(*p != '#')
            *username++ = *p++;
        //confirm
        FILE* LoginFile;
        LoginFile = fopen (USERFILE, "a+");
          if (fgetc(LoginFile) == EOF)
        {
                char *buff="admin#admin@";
                fputs(buff, LoginFile);
        }
            fseek(LoginFile, 0, SEEK_SET);
        char temp[50];
        while (fscanf(LoginFile, "%s@", temp) != EOF)
        {
            strcat(temp,"");
            //printf("%s ",temp);
            //printf("%s ",RecvBuf);
            if (strcmp (temp, RecvBuf) == 0)
            {
                printf("Log in success! ");
                send(ClientFd, "LOGI", 5, 0);
                fclose(LoginFile);
                return 1 ;
            }
        }
        send(ClientFd, "FAIL", 5, 0);
        fclose(LoginFile);
        return 0;
    }
     
    /***********************************************
    Function Name: Server_Sign
    Function: sign a new user in the Userlist
    Parameter:UserName, Password
    ************************************************/
    void Server_Sign(char* username, char* passwd)
    {
        FILE* SignFile;
        SignFile = fopen(USERFILE, "a+");
        fseek(SignFile, 0, SEEK_END);
        fputs(" ", SignFile);
        fputs(username, SignFile);
        fputs("#",SignFile);
        fputs(passwd, SignFile);
        fputs("@",SignFile);
        fclose(SignFile);
    }
     
     
    【client.c】
     
     
    /***********************************
    Version:2.0
    Program: client.c
    Content: 1.one server to offer many
             clients communicate server.
             2.add the function of sign
             and login.
    Records: shaw song  10/08 afternoon
             shaw song  10/10 morning
    ***********************************/
     
    #include "client.h"
     
    #define MyPort 8888
     
    int main(int argc, char ** argv)
    {
        //init var
        int ClientFd;
        struct sockaddr_in ClientAddr;
     
        char MyName[20];
        memset(MyName, '', 20);
        char buffer[140];
        memset(buffer, '',140);
        char DestName[20];
        memset(DestName,'',20);
        char SendName[20];
        memset(SendName,'',20);
        char SendMsg[100];
        memset(SendName,'',100);
     
        //input client name
        //printf("Please input the Client Name ");
        //scanf("%s", MyName);
     
        ClientFd = socket(AF_INET, SOCK_STREAM, 0);
        if (-1 == ClientFd)
        {
            perror("Socket Create fail");
            exit(1);
        }
     
        //connect
        ClientAddr.sin_family = AF_INET;
        ClientAddr.sin_port = htons(MyPort);
        ClientAddr.sin_addr.s_addr = inet_addr(argv[1]);
        memset(ClientAddr.sin_zero, 0, 8);
     
        if (connect(ClientFd, (struct sockaddr*)&ClientAddr, sizeof(ClientAddr)) < 0)
        {
            perror("connect  error");
            return 0;
        }
            printf("connect success! ");
     
        //Client Login
        if (Client_Login(ClientFd, MyName) == 0)
        {
            close(ClientFd);
            printf("Press any key to exit ");
            char t ;
            scanf("%c",&t);
            exit(0);
        }
     
        while(1)
        {
            //confirm if a message can receive
            fd_set FdSet;
            FD_ZERO(&FdSet);
            FD_SET(ClientFd, &FdSet);
            int ret;
            struct timeval tv;
            tv.tv_sec=1;
            tv.tv_usec=0;
                printf(" -------%s Message Receive------ ", MyName);
            while (1)
            {
                int tmp = select(ClientFd+1, &FdSet, NULL, NULL, &tv);
                if(!FD_ISSET(ClientFd, &FdSet) || tmp == 0)
                {
                    break;
                }
     
                ret = recv(ClientFd, buffer, sizeof(buffer), 0);
                if (ret <= 0)
                {
                    perror("recover fail");
                    close(ClientFd);
                    exit(1);
                }
     
                split_string(buffer,DestName,SendName,SendMsg);
                printf(" %s:%s ", SendName, SendMsg);
            }
                printf("-------------END--------------- ");
     
            /* function */
            int chs;
            printf(">>>>Please choose the number<<<< ");
            printf("1.Sign a new user ");
            printf("2.Talk to other Client ");
            printf("3.Quit and exit ");
            printf(">>>>>>>>>>>>>>><<<<<<<<<<<<<<<<< ");
            //scanf("%d",&chs);
            chs = ListenKeyboard();
            if (chs == 0)
                continue;
            if (chs == 1)
                Client_Sign(ClientFd);
            else if (chs == 2)
                Client_Talk(ClientFd, MyName);
            else if (chs == 3)
            {
                printf("Client Quit! ");
                close(ClientFd);
                return 0;
            }
     
       }
     
    }
     
     
    【client.h】
     
     
    /***********************************
    Version:2.0
    Program: client.h
    Content: 1.one server to offer many
             clients communicate server.
             2.add the function of sign
             and login.
    Records: shaw song  10/08 afternoon
             shaw song  10/10 morning
    ***********************************/
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/time.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
     
    /********************************
    Function Name:split_string
    Function:split the string buffer
             buffer:xxxxx#xxxx#xxxxx@
    Parameter: char* p is the buffer
               char* Dest Send Msg is
               the DestName SenderName
               and the Message Sended
    *********************************/
    void split_string(char* p, char* Dest, char* Send, char* Msg)
    {
        while(*p != '#')
            *Dest++ = *p++;
            p++;
        while(*p != '#')
            *Send++ = *p++;
            p++;
        while(*p != '@')
            *Msg++ = *p++;
    }
     
    /*********************************
    Function Name:Client_Login
    Function:Send the UserName and Passwd
             to Login
    Parameter: ClientFd is the fd of Client
    Return: type:int
            1 means Login Success
            0 means Login Fail
    ***********************************/
    int Client_Login(int ClientFd, char *myname)
    {
        char UserName[20];
        char Passwd[20];
        memset(UserName, '', 20);
        memset(Passwd, '', 20);
     
        printf("Please input your name : ");
        scanf("%s", UserName);
        memcpy(myname, UserName, 20);
        printf("Please input your password : ");
        scanf("%s", Passwd);
     
        //Send
        char SendBuf[50];
        memcpy(SendBuf, UserName, 20);
        strcat(SendBuf,"#");
        strcat(SendBuf, Passwd);
        strcat(SendBuf, "@");
     
        send(ClientFd, SendBuf, 50, 0);
     
        //recv
        char ans[5];
        int ret;
        ret = recv(ClientFd, ans, 5, 0);
        if (ret <= 0)
            return 0;
        if (memcmp(ans, "LOGI", 4) == 0)
        {
            printf("Login in Success! ");
            return 1;
        }
        else
        {
            printf("Login Fail!! Wrong username or passwd ");
            return 0;
        }
    }
     
    /****************************************
    Function Name: Client_Sign
    Function:sign a new user
    Parameter: ClientFd
    *****************************************/
    void Client_Sign(int ClientFd)
    {
        char UserName[20];
        char PassWord[20];
        char SendBuf[50];
        memset(UserName, '', 20);
        memset(PassWord, '', 20);
        memset(SendBuf, '', 50);
     
        printf("*****Sign a new user***** ");
        printf("Please input new Username: ");
        scanf("%s", UserName);
        printf("Please input the password: ");
        scanf("%s", PassWord);
        printf("************************** ");
     
        memcpy(SendBuf, "SIGN#", 6);
        strcat(SendBuf, UserName);
        strcat(SendBuf, "#");
        strcat(SendBuf, PassWord);
        strcat(SendBuf, "@");
     
        send(ClientFd, SendBuf, 50, 0);
     
    }
    /****************************************
    Function Name: Client_Talk
    Function:talk to other Client
    Parameter: ClientFd
    *****************************************/
    void Client_Talk(int ClientFd, char *MyName)
    {
            char SendName[20];
            char DestName[20];
            char SendMsg[100];
            char buffer[140];
            memset(SendName, '', 20);
            memset(DestName, '', 20);
            memset(SendMsg, '', 100);
            memset(buffer, '', 140); char ans='y';
            printf("Send Message ");
            if(ans == 'y')
            {
                printf("Please input the Dest Client Name:");
                scanf("%s", DestName);
                printf("Please input the Message:");
                    scanf("%s", SendMsg);
     
                strcpy(buffer,DestName);
                strcat(buffer, "#");
                strcat(buffer,MyName);
                strcat(buffer, "#");
                strcat(buffer,SendMsg);
                strcat(buffer, "@");
     
                int ret = send(ClientFd, buffer, sizeof(buffer), 0);
                if (ret > 0)
                {
                    printf("Message is sended! ");
                }
                else
                    printf("fail to send message! ");
            }
    }
     
    /*****************************************
    Function Name:ListenKeyboard
    Function:listen teh keyboard ,if there is a
             input then return
    *****************************************/
    int ListenKeyboard()
    {
        fd_set key;
        FD_ZERO(&key);
        FD_SET(0, &key);
        int KeyRet;
        int buf;
        struct timeval KeyTv;
        KeyTv.tv_sec =15;
        KeyTv.tv_usec = 0;
        KeyRet = select(1, &key, NULL, NULL, &KeyTv);
        if(KeyRet == 0)
        {
            system("clear");
            return 0;
        }
        else if(KeyRet > 0);
        {
            scanf("%d",&buf);
            return buf;
        }
        printf("wrong input! ");
    }
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    CodeForces:847D-Dog Show
    CodeForces 699C
    CodeForces:699B-One Bomb
    哈夫曼树:HDU5884-Sort(队列、哈夫曼树)
    Educational Codeforces Round 31- D. Boxes And Balls
    经典:区间dp-合并石子
    Codeforces Round #879 (Div. 2) C. Short Program
    卡顿
    异常断点
    自动布局
  • 原文地址:https://www.cnblogs.com/sslblog/p/5981352.html
Copyright © 2020-2023  润新知