1. 程式人生 > >專案:聊天室(TCP select架構)(連結串列)—— 客戶端

專案:聊天室(TCP select架構)(連結串列)—— 客戶端

標頭檔案:

#ifndef _CHATROOM1_H_
#define _CHATROOM1_H_


//************庫函式

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h> #include <pthread.h> #include <sqlite3.h> #include <time.h> #include <strings.h> #include <semaphore.h> #include <termios.h> #include <signal.h> //************巨集定義 #define PORT 8888 #define SUCCESS 10000000 #define FAILURE 10000001 #define RESIGER 1
#define LOGIN 2 #define OK 3 //傳送成功 #define ERROR 4 #define FIND 5 #define SAME 6 #define SEND 7 //傳送訊息 #define UN 8 //不線上 #define MSG 9 //收到悄悄話 #define NUM 10 //檢視線上人數 #define EXIT 11 #define GROUP 12 #define ERR 13 //群聊沒人線上 #define ES 14 //表情 #define PS 15 //常用語
#define VIP 16 #define TALK 17 //解禁 #define SHUTUP 18 //禁言 #define OKK 19 #define OUTLINE 20 #define OKKK 21 #define SENDFILE 22 #define UNRE 23 #define REOK 24 //**************執行緒 pthread_t tid = 0; //*************結構體 struct online // 線上連結串列 { int sockfd; char name[20]; struct online* next; }; typedef struct online* LinkList; struct senduser // 使用者資訊表 { char id[20]; char name[20]; char toname[20]; char password[20]; char code[20]; //密保 char msg[200]; char onlinenum[30][30]; //線上的人 char filename[20]; char filemsg[200]; int e_s; int p_s; int vip; //1是vip 0則不是 int state; //1是被禁言 0則不是 int number; //人數 int cmd; }; #endif

客戶端:

#include "chatroom1.h"

struct senduser User;
int OUT = 0;

int gettime()  
{  
    time_t rawtime;  
    struct tm * timeinfo;  
    time ( &rawtime );  
    timeinfo = localtime ( &rawtime );  
    printf ( "%s\n",asctime (timeinfo) );   
}  

void SCAN_N()
{
    char ch;
    while((getchar())!='\n'&&ch!=EOF);
}

void show()
{
    system("clear");
    printf("\t\t\t\t");
    gettime();
    printf("\t\t\t\t******************************\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*      歡迎來到聊天室!      *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t*                            *\n");
    printf("\t\t\t\t******************************\n");
    sleep(1);           
}

void mainshow()
{

    system("clear");
    printf("\t\t\t\t");
    gettime();
    printf("\t\t\t\t******************************\n\n\n");
    printf("\t\t\t\t         1.登入\n");
    printf("\t\t\t\t         2.註冊\n");
    printf("\t\t\t\t         3.忘記密碼\n");
    printf("\t\t\t\t         4.退出\n\n\n");
    printf("\t\t\t\t******************************\n");
    printf("\t\t\t\t*********輸入你的選擇*********\n");
}

void logging()
{
    system("clear");
    printf("\t\t\t\t");
    gettime();
    printf("\t\t\t\t******************************\n\n\n");
    printf("\t\t\t\t           正在登入中....     \n\n\n");
    printf("\t\t\t\t******************************\n");

}

void sending()
{
    system("clear");
    printf("\t\t\t\t");
    gettime();
    printf("\t\t\t\t******************************\n\n\n");
    printf("\t\t\t\t           正在傳送中....     \n\n\n");
    printf("\t\t\t\t******************************\n");

}

//*******************註冊***********************
int enroll(int sockfd)
{

    int ret;
    struct senduser User1;
    char password1[20];
    char password2[20];

    User1.vip = 0;
    User1.state = 0;

    system("clear");
    printf("\t\t\t\t");
    gettime();
    printf("\t\t\t\t******************************\n\n");
    printf("\t\t\t\t請輸入賬號:\n");
    printf("\t\t\t\t");
    scanf("%s", User1.id);
    SCAN_N();
    while(1)
    {
        printf("\t\t\t\t請輸入密碼:\n");
        printf("\t\t\t\t");
        scanf("%s", password1);
        SCAN_N();
        printf("\t\t\t\t再次輸入密碼:\n");
        printf("\t\t\t\t");
        scanf("%s", password2);                 
        SCAN_N();

        if(strcmp(password1, password2) == 0)
        {                           
            printf("\t\t\t\t輸入密碼成功!\n");
            strcpy(User1.password, password1);  
            break;
        }
        else
        {
            printf("\t\t\t\t兩次輸入不相同,請重新輸入!\n");
        }
    }

    printf("\t\t\t\t請輸入暱稱:\n");
    printf("\t\t\t\t");
    scanf("%s", User1.name);
    SCAN_N();

    printf("\t\t\t\t密保:請輸入六位數字\n");
    printf("\t\t\t\t");
    scanf("%s", User1.code);
    SCAN_N();

    User1.cmd = RESIGER;

    ret = send(sockfd, &User1, sizeof(User1), 0);
    if(ret == -1)
    {
        perror("send");
        return FAILURE;
    }

    ret = recv(sockfd, &User1, sizeof(User1), 0);
    if(User1.cmd == UNRE)
    {
        system("clear");
        printf("\t\t\t\t註冊失敗!\n");
        sleep(1);
    }
    if(User1.cmd == REOK)
    {
        system("clear");
        printf("\t\t\t\t註冊成功!\n");
        sleep(1);
    }
}

//***************************登入****************
int login(int sockfd)
{
    int ret;


    while(1)
    {
        system("clear");
        printf("\t\t\t\t");
        gettime();
        printf("\t\t\t\t******************************\n\n");
        printf("\t\t\t\t請輸入您的賬號:\n");
        printf("\t\t\t\t");
        scanf("%s", User.id);
        SCAN_N();
        printf("\t\t\t\t請輸入密碼:\n");
        printf("\t\t\t\t");
        scanf("%s", User.password);
        SCAN_N();

        User.cmd = LOGIN;
        ret = send(sockfd, &User, sizeof(User), 0);
        if(ret == -1)
        {
            perror("LOGINsend");
            return FAILURE;
        }

        memset(&User, 0, sizeof(User));
        ret = recv(sockfd, &User, sizeof(User), 0); 
        if(User.cmd == OK)
        {
            return 1;
        }
        else if(User.cmd == SAME)
        {
            return 3;
        }
        else if(User.cmd == ERROR)
        {
            printf("\t\t\t\t登入錯誤!請重新輸入正確賬號和密碼!\n");
            sleep(1);
        }
    }
}

//****************************忘記密碼********************
int find(int sockfd)
{
    int ret;
    struct senduser User1;

    while(1)
    {
        system("clear");
        printf("\t\t\t\t");
        gettime();
        printf("\t\t\t\t請輸入您的賬號:\n");
        printf("\t\t\t\t");
        scanf("%s", User1.id);
        SCAN_N();

        printf("\t\t\t\t請輸入您的密保答案:\n");
        printf("\t\t\t\t");
        scanf("%s", User1.code);
        SCAN_N();

        printf("\t\t\t\t請輸入修改的密碼:\n");
        printf("\t\t\t\t");
        scanf("%s", User1.password);
        SCAN_N();

        User1.cmd = FIND;

        ret = send(sockfd, &User1, sizeof(User1), 0);
        if(ret == -1)
        {
            perror("findsend");
            return FAILURE;
        }

        ret = recv(sockfd, &User1, sizeof(User1), 0);
        if(ret == -1)
        {
            perror("findrecv");
            return FAILURE;
        }
        if(User1.cmd == OK)
        {
            printf("\t\t\t\t修改成功!\n");
            sleep(1);
            break;
        }
        else
        {
            sleep(1);
            printf("\t\t\t\t修改失敗!請輸入正確的賬號和密碼!\n");
        }
    }
}

void sendps(int n, char *name)
{
    switch(n)
    {
        case 1:
            printf("\t\t\t\t %s給您傳送了一句話:\n", name);
            printf("\t\t\t\t        How are you doing?\n");
            break;
        case 2:
            printf("\t\t\t\t %s給您傳送了一句話:\n", name);
            printf("\t\t\t\t        What's up?\n");
            break;
        case 3:
            printf("\t\t\t\t %s給您傳送了一句話:\n", name);
                printf("\t\t\t\t    May I have your name, please?\n");
            break;
        case 4:
            printf("\t\t\t\t %s給您傳送了一句話:\n", name);
                printf("\t\t\t\t    I'm glad to have met you.\n");
            break;
        case 5:
            printf("\t\t\t\t %s給您傳送了一句話:\n", name);
            printf("\t\t\t\t        Keep in touch.\n");
            break;
        case 6:
            printf("\t\t\t\t %s給您傳送了一句話:\n", name);
            printf("\t\t\t\t        Same to you.\n");
            break;
    }
}

void sendes(int n, char *name)
{
    switch(n)
    {
        case 1:
            printf("\t\t\t\t %s向您傳送了一個表情:\n", name);
            printf("\t\t\t\t    .҉٩(*´︶`*)۶҉我跳起來就是一個麼麼噠\n");
            break;
        case 2:
            printf("\t\t\t\t %s向您傳送了一個表情:\n", name);
            printf("\t\t\t\t    .╮(︶﹏︶)鬼知道我經歷了什麼\n");
            break;
        case 3:
            printf("\t\t\t\t %s向您傳送了一個表情:\n", name);
            printf("\t\t\t\t    ٩(๑´0`๑)۶ 還我假期\n");
            break;
        case 4:
            printf("\t\t\t\t %s向您傳送了一個表情:\n", name);
            printf("\t\t\t\t    _(:ι」∠)_好餓,但是不想動\n");
            break;
        case 5:
            printf("\t\t\t\t %s向您傳送了一個表情:\n", name);
            printf("\t\t\t\t    _(:3」∠)_  我的床需要我!\n");
            break;
    }
}
//***************************禁言****************************

int shutup(int sockfd)
{
    int ret;
    int m;
    char n[20];

    if(User.state == 1)
    {
        system("clear");
        printf("\t\t\t\t***********************************\n\n");
        printf("\t\t\t\t您正處於被禁言狀態!是否解禁?\n");
        printf("\t\t\t\t     1.霸氣解禁! 2.做個安靜的美男子也挺好\n");
        printf("\t\t\t\t");
        scanf("%d", &m);
        SCAN_N();
        if(m == 1)
        {
            if(User.vip == 1)
            {
                User.state = 0;
                User.cmd = TALK;
                ret = send(sockfd, &User, sizeof(User), 0);
                if(ret == -1)
                {
                    perror("sendtalk");
                    return FAILURE;
                }
                printf("\t\t\t\t 解禁成功!盡情發言吧!\n");
                sleep(1);
            }
            else 
            {
                printf("\t\t\t\t 抱歉!您還不是我們尊貴的會員,不可以解禁噢!\n");
                sleep(1);
            }
        }
    }
    system("clear");
    printf("\t\t\t\t***********************************\n\n");
    printf("\t\t\t\t您想要禁言哪位好友?\n");
    printf("\t\t\t\t   輸入好友的名字或者輸入0退出\n");
    printf("\t\t\t\t");
    scanf("%s", n);
    if(strcmp(n, "0") == 0)
    {
        return 0;
    }
    else
    {
        strcpy(User.toname, n);
        User.cmd = SHUTUP;
        ret = send(sockfd, &User, sizeof(User), 0);
        if(ret == -1)
        {
            perror("sendshutup");
            return 0;
        }

    }

}



//*******************************登陸後接收的訊息***********************
void *Recv(void *sockfd)
{
    FILE *fp;
    int ret;
    struct senduser Recv = {0};
    int i;
    char text3[30];
    char text4[100];

    while(1)
    {
        ret = recv(*(int *)sockfd, &Recv, sizeof(Recv), 0);
        if(-1 == ret)
        {
            perror("recv");
            exit(1);
        }

        switch(Recv.cmd)
        {
            case (MSG):
                system("clear");
                memset(text3, 0, sizeof(text3));
                memset(text4, 0, sizeof(text4));
                sprintf(text3, "%s和%s的聊天記錄.text", Recv.toname, Recv.name);
                fp = fopen(text3, "a");
                if(fp == NULL)
                {
                    perror("fopen");
                    exit(1);
                }

                sprintf(text4, "%s:%s", Recv.name, Recv.msg);
                ret = fwrite(text4, 1, sizeof(text4), fp);
                if(ret == 0)
                {
                    perror("fwrite");
                    exit(1);
                }

                fclose(fp);

                printf("\t\t\t\t%s向您傳送了一條悄悄話:%s\n", Recv.name, Recv.msg);
                printf("\t\t\t\t輸入p返回\n");
                memset(&Recv.cmd,0,sizeof(Recv.cmd));
                break;
            case (OK):
                system("clear");
                printf("\t\t\t\t傳送成功!\n");
                memset(&Recv.cmd,0,sizeof(Recv.cmd));
                break;
            case (UN):
                system("clear");
                printf("\t\t\t\t此使用者不線上!\n");
                memset(&Recv.cmd,0,sizeof(Recv.cmd));
                break;
            case (NUM):
                system("clear");
                printf("\t\t\t\t現在線上的人數是:%d\n", Recv.number);
                if(Recv.number == 0)
                {
                    printf("\t\t\t\t無人線上!\n");
                    break;
                }
                printf("\t\t\t\t線上的人是:\n");
                printf("\t\t\t\t");
                for(i = 0; i < Recv.number; i++)
                {
                    printf("%s ", Recv.onlinenum[i]);
                }
                printf("\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (GROUP):
                system("clear");
                printf("\t\t\t\t收到來自%s的一條群發信息:\n", Recv.name);
                printf("\t\t\t\t%s", Recv.msg);
                printf("\n");
                printf("\t\t\t\t輸入p返回\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (ERR):
                system("clear");
                printf("\t\t\t\t無人線上!\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (PS):
                system("clear");
                sendps(Recv.p_s, Recv.name);
                printf("\t\t\t\t輸入p返回\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (ES):
                system("clear");
                sendes(Recv.e_s, Recv.name);
                printf("\t\t\t\t輸入p返回\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (OKK):
                system("clear");
                printf("\t\t\t\t禁言成功!\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (SHUTUP):
                User.state = 1;
                system("clear");
                printf("\t\t\t\t 您已經被%s禁言了!\n", Recv.name);
                printf("\t\t\t\t 開通會員即可解禁!\n");
                printf("\t\t\t\t輸入p返回\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (OKKK):
                system("clear");
                printf("\t\t\t\t踢人成功!\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                printf("\t\t\t\t 輸入'p'返回\n");
                break;
            case (SENDFILE):
                fp = fopen("MyRecv.text", "a");
                ret = fwrite(Recv.filemsg, 1, strlen(Recv.filemsg), fp);
                if(ret == 0)
                {
                    perror("recvfile");
                    break;
                }
                fclose(fp);
                system("clear");
                printf("\t\t\t\t 您成功收到來自好友%s傳送的一份檔案!\n", Recv.name);
                printf("\t\t\t\t輸入p返回\n");
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                break;
            case (OUTLINE):
                OUT = 1;
                system("clear");
                printf("\t\t\t\t 您被好友%s踢下線!\n", Recv.name);
                memset(&Recv.cmd, 0, sizeof(Recv.cmd));
                printf("\t\t\t\t輸入'x'返回\n");
                break;

        }

    }
}

//************************聊天主介面***************
int menushow()
{
    system("clear");
    printf("\t\t\t\t");
    gettime();
    printf("\t\t\t\t*********************************\n");
    printf("\t\t\t\t                               \n");
    printf("\t\t\t\t          小王子聊天室         \n");
    printf("\t\t\t\t                               \n");
    printf("\t\t\t\t  暱稱:%s                     \n", User.name);
    printf("\t\t\t\t                               \n");
    printf("\t\t\t\t             a.悄悄話          \n");
    printf("\t\t\t\t             b.群發            \n");
    printf("\t\t\t\t             c.檢視線上人數    \n");
    printf("\t\t\t\t             d.檢視聊天記錄    \n");
    printf("\t\t\t\t             e.傳送常用語句    \n");
    printf("\t\t\t\t             f.傳送常用表情    \n");
    printf("\t\t\t\t             g.辦理會員        \n");
    printf("\t\t\t\t             h.禁言管理        \n");
    printf("\t\t\t\t             i.踢人管理        \n");
    printf("\t\t\t\t             j.檔案傳輸        \n");
    printf("\t\t\t\t             z.下線            \n");
    printf("\t\t\t\t                               \n");
    printf("\t\t\t\t*********************************\n");

}


int menu(int sockfd)
{
    FILE *fp;
    int j = 0;
    char bs;
    char msgg[100];
    int ret;
    char choice[10];
    char name1[20];
    char text1[30];
    char text2[100];


    while(1)
    {
        menushow();
        printf("\t\t\t\t選擇您想要的功能:\n");
        printf("\t\t\t\t");
        scanf("%s", choice);
        SCAN_N();
        switch(choice[0])
        {
            case 'a':
                system("clear");
                printf("\t\t\t\t");
                gettime();
                if(User.state == 1)
                {
                    printf("\t\t\t\t您已被禁言!\n");
                    sleep(1);
                    break;
                }
                printf("\t\t\t\t您想要發悄悄話給哪位好友?\n");
                printf("\t\t\t\t");
                scanf("%s", User.toname);
                SCAN_N();  
                printf("\t\t\t\t請輸入您想要傳送的訊息:\n");
                printf("\t\t\t\t");
                scanf("%s", User.msg);
                SCAN_N();  

                memset(text1, 0, sizeof(text1));
                memset(text2, 0, sizeof(text2));
                sprintf(text1, "%s和%s的聊天記錄.text", User.name, User.toname);
                fp = fopen(text1, "a");
                if(fp == NULL)
                {
                    perror("open");
                    return FAILURE;
                }

                sprintf(text2, "%s:%s", User.name, User.msg);
                ret = fwrite(text2, 1, sizeof(text2), fp);
                if(ret == 0)
                {
                    perror("write");
                    return FAILURE;
                }


                fclose(fp);

                User.cmd = SEND;
                ret = send(sockfd, &User, sizeof(User), 0);
                if(ret == -1)
                {
                    perror("senfmsg");
                    return FAILURE;
                }
                sending();
                sleep(1);

                break;
            case 'b':
                system("clear");
                if(User.state == 1)
                {
                    printf("\t\t\t\t您已被禁言!\n");
                    sleep(1);
                    break;
                }
                printf("\t\t\t\t輸入您想傳送的話:\n");
                printf("\t\t\t\t");
                scanf("%s", User.msg);
                SCAN_N();

                User.cmd = GROUP;

                ret = send(sockfd, &User, sizeof(User), 0);
                if(ret == -1)
                {
                    perror("group");
                    return FAILURE;
                }
                sending();
                sleep(1);

                break;
            case 'c':
                User.cmd = NUM;
                ret = send(sockfd, &User, sizeof(User), 0);
                if(ret == -1)
                {
                    perror("sendnum");
                    return FAILURE;
                }
                break;
            case 'd':
                memset(name1, 0, sizeof(name1));
                memset(text1, 0, sizeof(text1));
                system("clear");
                printf("\t\t\t\t請問想要檢視和誰的聊天記錄?\n");
                scanf("%s", name1);
                SCAN_N();

                sprintf(text1, "%s和%s的聊天記錄.text", User.name, name1);
                fp = fopen(text1, "r");
                if(fp == NULL)
                {
                    printf("\t\t\t\t沒有與此好友的聊天記錄!\n");
                    break;
                }

                while(1)
                {
                    memset(msgg, 0, sizeof(msgg));
                    ret = fread(msgg, 1, sizeof(msgg), fp);
                    if(ret == 0)
                    {
                        break;
                    }
                    printf("%s\n", msgg);
                }

                sleep(3);
                fclose(fp);
                break;
            case 'e':
                User.cmd = PS;
                if(User.state == 1)
                {
                    system("clear");
                    printf("\t\t\t\t您已被禁言!\n");
                    sleep(1);
                    break;
                }
                system("clear");
                printf("\t\t\t\t***********************************\n");
                printf("\t\t\t\t您想要傳送給誰?\n");
                printf("\t\t\t\t");
                scanf("%s", User.toname);
                SCAN_N();

                system("clear");
                printf("\t\t\t\t***********************************\n");
                printf("\t\t\t\t 1.How are you doing?\n");
                printf("\t\t\t\t 2.What's up?\n");
                printf("\t\t\t\t 3.May I have your name, please?\n");
                printf("\t\t\t\t 4.I'm glad to have met you.\n");
                printf("\t\t\t\t 5.Keep in touch.\n");
                printf("\t\t\t\t 6.Same to you.\n");
                printf("\t\t\t\t***********************************\n");
                printf("\t\t\t\t選擇想要傳送的常用語?\n");
                scanf("%d", &User.p_s);
                SCAN_N();

                ret = send(sockfd, &User, sizeof(User), 0);
                if(ret == -1)
                {
                    perror("sendps");
                    return FAILURE;
                }
                sending();
                sleep(1);
                break;
            case 'f':
                if(User.state == 1)
                {
                    system("clear");
                    printf("\t\t\t\t您已被禁言!\n");
                    sleep(1);
                    break;
                }
                User.cmd = ES;
                system("clear");
                printf("\t\t\t\t***********************************\n");
                printf("\t\t\t\t您想要傳送給誰?\n");
                printf("\t\t\t\t");
                scanf("%s", User.toname);
                SCAN_N();

                system("clear");
                printf("\t\t\t\t***********************************\n");
                printf("\t\t\t\t 1..҉٩(*´︶`*)۶҉我跳起來就是一個麼麼噠\n");
                printf("\t\t\t\t 2..╮(︶﹏︶)鬼知道我經歷了什麼\n");
                printf("\t\t\t\t 3.٩(๑´0`๑)۶ 還我假期\n");
                printf("\t\t\t\t 4._(:ι」∠)_好餓,但是不想動\n");
                printf("\t\t\t\t 5._(:3」∠)_  我的床需要我!\n");
                printf("\t\t\t\t***********************************\n");
                printf("\t\t\t\t 選擇您想要傳送的表情\n");
                scanf("%d", &User.e_s);
                SCAN_N();

                ret = send(sockfd, &User, sizeof(User), 0);
                if(ret == -1)
                {
                    perror("sendes");
                    return FAILURE;
                }
                sending();
                sleep(1);

                break;
            case 'g':
                system("clear");