1. 程式人生 > >用UDP實現簡易的聊天室

用UDP實現簡易的聊天室

由於UDP封裝函式較少,所以我沒有用封裝函式

標頭檔案

#ifndef _CHAT_H_
#define _CHAT_H_

#include <stdio.h>  
#include <sqlite3.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <string.h>  
#include <strings.h>  
#include <stdlib.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <unistd.h> #include <signal.h> #include <pthread.h> #include <semaphore.h> #include <termios.h> #include <time.h> #include <sys/stat.h> #include <fcntl.h> #define PORT 9999 #define reg 11 //註冊,cmd #define reg_success 12 //註冊成功
#define existing 13 //賬號已存在 #define log_in 14 //登入,cmd #define log_success 15 //登入成功 #define logged 16 //賬號已登入 #define log_error 17 //賬號或密碼錯誤 #define private_chat 18 //私聊 #define group_chat 19 //群聊 #define Gchat_failure 20 //群聊失敗 #define online 21 //線上人數
#define Vip 22 //會員 #define shutup 23 //禁言 #define relieve 24 //解除禁言 #define kick 25 //踢人 #define face 26 //群發表情 #define send_useful 27 //傳送常用語 #define Exit 28 //退出 #define quit 31 //下線 #define Send_success 29 //傳送成功 #define Pchat_failure 30 //私聊失敗 #define Send_failure 32 //傳送失敗 #define face_failure 33 //傳送表情失敗 #define vip_success 34 //開通會員成功 #define shutup_success 35 //禁言成功 #define kick_success 36 //踢人成功 #define shutup_failure 37 //禁言失敗 #define kick_failure 38 //踢人失敗 #define send_file 39 //傳送檔案 #define accept_file 40 //接收檔案 #endif

伺服器程式碼

#include "chat.h"

struct info
{
    char username[20];          //使用者名稱     
    char password[20];          //密碼   
    int cmd;                    //提取操作符  
    int result;                 //返回標記
    int port;                   //埠號
    char message[50];           
    char toname[20];            
    char fromname[20];          
    char online_name[20][20];   
    int num;                    
    int p_f;                    
    char emoj[20];              
    int p_u;                    
    char useful[20];            
    int vip;                    
    char question[50];          
    char answer[50];            
    char file_name[50];         
    char file_content[2048];    
};

struct node
{
    struct sockaddr_in client_addr;
    char name[20];
    struct node *next;
};

typedef struct node Node;
typedef Node *Lnode;

struct info RecvBuf;
struct info SendBuf;
sqlite3 *ppdb = NULL;
int ret;
int sockfd;
Lnode head = NULL;

//註冊
void register1()  
{  
    char sql[100] = {0};     

    sprintf(sql, "insert into chat(username,password,vip) values('%s','%s','%d')",RecvBuf.username, RecvBuf.password,RecvBuf.vip);  

    char *errmsg = NULL;
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, &errmsg);  
    if(ret != SQLITE_OK)  
    {  
        perror("sqlite3_exec2");
        SendBuf.result = existing;
        printf("%s is insert failure:%s\n",RecvBuf.username, errmsg);  
        return;  
    }  

    printf("user insert success!\n");  
    SendBuf.result = reg_success;
}

//登入
void login(struct sockaddr_in tmp_addr)
{
    char sql[100] = {0};
    char **Result = NULL;//返回記錄,二維陣列
    int nrow; //行數
    int ncolumn; //列數
    int ret;
    int i;

    sprintf(sql, "select username, password ,vip from chat where username = '%s' and password = '%s'", RecvBuf.username, RecvBuf.password);
    ret = sqlite3_get_table(ppdb, sql, &Result, &nrow, &ncolumn, NULL);
    if (ret != SQLITE_OK)
    {
        perror("sqlite3_get_table_login");
        return;
    }

    if(1 == nrow)
    {
        Lnode tmp = head->next;
        Lnode p =(Lnode)malloc(sizeof(Node));
        if(p == NULL)
        {
            printf("FAILURE!\n");
            return;
        }
        while(tmp != head)  
        {  
            if(!strcmp(tmp->name, Result[3]))  
            {    
                printf("您的賬號已登入!\n"); 
                SendBuf.result = logged;
                return;  
            }  
            tmp = tmp->next;  
        }

        SendBuf.result = log_success;

        strcpy(p->name,Result[3]);
        strcpy(SendBuf.username,Result[3]);
        SendBuf.vip = *(Result[5]) - 48;

        p->client_addr.sin_family = tmp_addr.sin_family;
        p->client_addr.sin_port = tmp_addr.sin_port;
        p->client_addr.sin_addr.s_addr = tmp_addr.sin_addr.s_addr;
        printf("%s的埠號是%d\n",p->name,p->client_addr.sin_port);
        p->next = head->next;
        head->next = p;

        printf("%s is logging!\n",Result[3]);
    }

    else
    {
        SendBuf.result = log_error;
        printf("您的賬號或密碼錯誤,請重新登入!\n");
    }
}


//處理私聊
int deal_private(struct sockaddr_in tmp_addr)
{
    int postion = 0;
    Lnode tmp = head->next;
    while(tmp != head)
    {
        if(strcmp(tmp->name,RecvBuf.toname) == 0 )
        {
            postion = 1;
            strcpy(SendBuf.message,RecvBuf.message);
            strcpy(SendBuf.fromname,RecvBuf.username);

            SendBuf.result = private_chat;
            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if(ret == -1)
            {
                perror("sendto_chat");
                exit(1);
            }
            break;
        }
        tmp=tmp->next;
    }

    if(postion)
    {
        SendBuf.result=Send_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if(ret == -1)
        {
            perror("sendto_success");
            exit(1);
        }
    }
    else
    {
        SendBuf.result=Pchat_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if(ret == -1)
        {
            perror("sendto_failure");
            exit(1);
        }
    }
}

//處理群聊
int deal_group(struct sockaddr_in tmp_addr)
{
    int postion = 0;
    Lnode tmp = head->next;
    while (tmp != head)
    {
        if (tmp->client_addr.sin_port != tmp_addr.sin_port)
        {
            postion = 1;

            SendBuf.result = group_chat;
            strcpy(SendBuf.fromname, RecvBuf.username);
            printf("5555%s\n",SendBuf.fromname);
            strcpy(SendBuf.message, RecvBuf.message);
            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if (ret < 0)
            {
                perror("sendto_group_chat");
                exit(1);
            }
        }
        tmp = tmp->next;
    }
    if (1 == postion)
    {
        SendBuf.result = Send_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_group_chat_success");
            exit(1);
        }
    }
    else 
    {
        SendBuf.result = Gchat_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_group_chat_failure");
            exit(1);
        }
    }
}

//處理線上人數
int deal_online()
{
    int i = 0;
    SendBuf.num = 0;
    Lnode tmp = head->next;
    while(tmp != head)
    {
        SendBuf.num++;
        strcpy(SendBuf.online_name[i],tmp->name);
        i++;
        tmp = tmp->next;
    }
    SendBuf.result = online;
}

//處理群發表情
int deal_face(struct sockaddr_in tmp_addr)
{
    int postion = 0;
    Lnode tmp = head->next;
    while (tmp != head)
    {
        if (tmp->client_addr.sin_port != tmp_addr.sin_port)
        {
            postion = 1;

            SendBuf.result = face;
            strcpy(SendBuf.fromname, RecvBuf.username);
            SendBuf.p_f = RecvBuf.p_f;
            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if (ret < 0)
            {
                perror("sendto_face");
                exit(1);
            }
        }
        tmp = tmp->next;
    }
    if (1 == postion)
    {
        SendBuf.result = Send_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_face_success");
            exit(1);
        }
    }
    else
    {
        SendBuf.result = face_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_face_failure");
            exit(1);
        }
    }
}

//處理髮送常用語
int deal_useful(struct sockaddr_in tmp_addr)
{
    int postion = 0;
    Lnode tmp = head->next;
    while(tmp != head)
    {
        if(strcmp(tmp->name,RecvBuf.toname) == 0 )
        {
            postion = 1;
            SendBuf.result = send_useful;
            SendBuf.p_u = RecvBuf.p_u;
            strcpy(SendBuf.fromname,RecvBuf.username);
            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if(ret == -1)
            {
                perror("sendto_useful");
                exit(1);
            }
            break;
        }
        tmp=tmp->next;
    }

    if(postion)
    {
        SendBuf.result = Send_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if(ret == -1)
        {
            perror("sendto_success");
            exit(1);
        }
    }
    else
    {
        SendBuf.result = Send_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if(ret == -1)
        {
            perror("sendto_failure");
            exit(1);
        }
    }
}

//處理vip
int deal_vip(struct sockaddr_in tmp_addr)
{
    char sql[100] = {0};

    sprintf(sql,"update chat set vip= %d where username = '%s';",RecvBuf.vip,RecvBuf.username);

    ret = sqlite3_exec(ppdb,sql,NULL,NULL,NULL);
    if(ret!=SQLITE_OK)
    {
        perror("sqlite3_exec");
        return;
    }

    SendBuf.vip = 1;
    SendBuf.result = vip_success;
    ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
    if(ret == -1)
    {
        perror("sendto_vip_failure");
        exit(1);
    }
    printf("%s become vip ...\n",SendBuf.username);
    return 0;

}

//處理禁言
int deal_shutup(struct sockaddr_in tmp_addr)
{
    Lnode tmp = head->next;
    int postion = 0;
    while(tmp != head)
    {
        if(strcmp(tmp->name,RecvBuf.toname)==0)
        {
            postion = 1;
            SendBuf.result = shutup;
            strcpy(SendBuf.fromname,RecvBuf.username);
            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if (ret < 0)
            {
                perror("sendto_shutup");
                return;
            }

        }
        tmp = tmp->next;
    }
    if(postion)
    {
        SendBuf.result = shutup_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_shutup_success");
            return;
        }
    }
    else
    {
        SendBuf.result = shutup_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_shutup_failure");
            return;
        }
    }
}

//處理踢人
int deal_kick(struct sockaddr_in tmp_addr)
{   
    int postion = 0;

    Lnode tmp = head->next;

    while(tmp != head)
    {
        if(strcmp(tmp->name, RecvBuf.toname ) == 0)
        {
            postion = 1;

            SendBuf.result = kick;
            strcpy(SendBuf.fromname,RecvBuf.username);
            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if (ret < 0)
            {
                perror("sendto_kick");
                return;
            }

            Lnode p = tmp->next;
            tmp->next = p->next;
            free(p);
            printf("%s logged out...\n", RecvBuf.username );

            break;
        }
        tmp = tmp->next;
    }

    if(postion == 1)
    {
        SendBuf.result = kick_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_kick_success");
            exit(1);
        }
    }
    else
    {
        SendBuf.result = kick_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_shutup_failure");
            exit(1);
        }
    }
}

//處理檔案傳輸
int deal_sendfile(struct sockaddr_in tmp_addr)
{
    int postion = 0;
    Lnode tmp = head->next;

    while (tmp != head)
    {
        if (strcmp(tmp->name,RecvBuf.toname) == 0)
        {
            postion = 1;
            strcpy(SendBuf.fromname,RecvBuf.username);
            strcpy(SendBuf.file_name, RecvBuf.file_name);//拷貝檔名
            strcpy(SendBuf.file_content, RecvBuf.file_content);//拷貝檔案內容

            SendBuf.result = accept_file;

            ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp->client_addr, sizeof(tmp->client_addr));
            if (ret < 0)
            {
                perror("sendto_sendfile");
                return;
            }
        }
        tmp = tmp->next;
    }

    if (1 == postion)
    {
        SendBuf.result = Send_success;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_file_success");
            return;
        }
    }
    else 
    {
        SendBuf.result = Send_failure;
        ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&tmp_addr, sizeof(tmp_addr));
        if (ret < 0)
        {
            perror("sendto_file_failure");
            return;
        }
    }
}

//處理下線
int deal_quit()
{
    Lnode tmp = head;

    if(tmp->next->next == head)
    {
        if(strcmp(tmp->next->name, RecvBuf.username ) == 0)
        {
            Lnode p = tmp->next;
            tmp->next = p->next;
            free(p);
            printf("%s logged out...\n", RecvBuf.username );
            return;
        }
        tmp = tmp->next;
    }

    while(tmp->next != head)
    {
        if(strcmp(tmp->next->name, RecvBuf.username ) == 0)
        {
            SendBuf.result = quit;
            Lnode l = tmp->next;
            tmp->next = l->next;
            free(l);
            printf("%s logged out...\n", RecvBuf.username );
            break;
        }
        tmp = tmp->next;
    }

    return 0;
}

int main()
{
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int length;
    int position;
    char sql[100] = {0};

    head = (Lnode)malloc(sizeof(Node));
    if (NULL == head)
    {
        printf("Malloc Failure!\n");
        return;
    }
    head->next = head;

    sockfd = socket(PF_INET, SOCK_DGRAM, 0);
    if (-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = PORT;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (ret < 0)
    {
        perror("bind");
        exit(1);
    }

    ret = sqlite3_open("chat.db", &ppdb);
    if (ret != SQLITE_OK)
    {
        perror("sqlite3_open");
        exit(1);
    }

    sprintf(sql, "create table if not exists chat (username text primary key, password text,vip integer);");
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if (ret != SQLITE_OK)
    {
        perror("sqlite3_exec1");
        exit(1);
    }

    while (1)
    {
        length = sizeof(client_addr);
        ret = recvfrom(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&client_addr, &length);
        if (ret < 0)
        {
            perror("recvfrom");
            exit(1);
        }

        printf("Recv From Client %d\n", client_addr.sin_port);

        printf("11%s\t%s\n", RecvBuf.username, RecvBuf.password);

        switch (RecvBuf.cmd)  
        {  
            case (reg):                    //註冊  
            {   
                register1();
                ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
                if (ret < 0)
                {
                    perror("sendto_server_register");
                    exit(1);
                }

                break;
            }

            case (log_in):                //登入
            {
                login(client_addr);
                ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
                if (ret < 0)
                {
                    perror("sendto_server_log_in");
                    exit(1);
                }
                break;
            }

            case (private_chat):      //私聊
            {
                deal_private(client_addr);
                break;
            }

            case(group_chat):           //群聊
            {
                deal_group(client_addr);
                break;
            }

            case(online):             //檢視線上人數
            {
                deal_online();
                ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
                if(ret == -1)
                {
                    perror("sendto_online");
                }
                break;
            }

            case(face):      //群發表情
            {
                deal_face(client_addr);
                break;
            }

            case(send_useful):   //傳送常用語
            {
                deal_useful(client_addr);
                break;
            }

            case(Vip):              //開通會員
            {
                deal_vip(client_addr);
                break;
            }

            case(shutup):           //禁言
            {
                deal_shutup(client_addr);
                break;
            }

            case(kick):              //踢人
            {
                deal_kick(client_addr);
                break;
            }

            case (send_file):         //檔案傳輸
            {
                deal_sendfile(client_addr);
                break;
            }

            case(quit):       //下線
            {
                deal_quit();
                ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
                if(ret == -1)
                {
                    perror("sendto_quit");
                }
                break;
            }
        }           
    }

    sqlite3_close(ppdb);  

    return 0;
}

客戶端程式碼

#include "chat.h"

struct info
{
    char username[20];       //使用者名稱     
    char password[20];       //密碼   
    int cmd;                 //提取操作符 
    int result;              //返回標記
    int port;                //埠號
    char message[50];
    char toname[20];
    char fromname[20];
    char online_name[20][20];
    int num;
    int p_f;
    char emoj[20];
    int p_u;
    char useful[20];
    int vip;
    char question[50];
    char answer[50];
    char file_name[50];
    char file_content[2048];
};

struct info SendBuf ;
struct info RecvBuf ;
struct sockaddr_in server_addr;
char name[20] = {0};
int ret;
int sockfd;
int flag;
int out = 0;

//時間函式
void time_show()
{
     time_t rawtime;
     struct tm *timeinfo;
     time (&rawtime);
     timeinfo = localtime(&rawtime);
     printf("時間: %d 年 %d 月 %d 日 %d 時 %d 分 %d 秒\n\n", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
                timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

}

void welcome(void)
{
    system("clear");
    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*        Welcome To ZQP Chatting Room !     *\n");
    printf("\t\t\t\t*                                           *\n");
    printf("\t\t\t\t*                                           *\n");
    printf("\t\t\t\t*                                           *\n");
    printf("\t\t\t\t*                                Author:ZQP *\n");
    printf("\t\t\t\t*********************************************\n");

    sleep(2);
}

void bye(void)
{
    system("clear");
    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*        Hope To See You Again !            *\n");
    printf("\t\t\t\t*                                           *\n");
    printf("\t\t\t\t*                                           *\n");
    printf("\t\t\t\t*                                           *\n");
    printf("\t\t\t\t*                                Author:ZQP *\n");
    printf("\t\t\t\t*********************************************\n");

    sleep(2);

}

void show()  
{  
    system("clear");  
    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*     1  註冊                                *\n");  
    printf("\t\t\t\t*     2  登入                                *\n");
    printf("\t\t\t\t*     3  退出                                *\n");
    printf("\t\t\t\t*                                            *\n"); 
    printf("\t\t\t\t*     請輸入選擇:                           *\n");
    printf("\t\t\t\t**********************************************\n");
}

//防止空格影響
void SCAN_N()  
{  
    char ch;  
    while((getchar()) != '\n' && ch != EOF);  
}  

//登入之後的聊天介面
int chatshow() 
{
    system("clear");
    printf("\t\t\t\t");
    time_show();

    printf("\t\t\t\t**********************************************\n");  
    printf("\t\t\t\t*   歡迎來到小仙女的聊天室!祝您聊天愉快!    *\n"); 
    printf("\t\t\t\t*   使用者名稱:%s                                *\n",name);
    if(SendBuf.vip == 1)
    {
        printf("\t\t\t\t*   尊貴的會員                            *\n");
    }
    else
    {
        printf("\t\t\t\t*   普通使用者                               *\n");
    }
    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*                k 解禁                      *\n");
    printf("\t\t\t\t*                z 退出                      *\n");  
    printf("\t\t\t\t*                請輸入您的選擇:            *\n");
    printf("\t\t\t\t**********************************************\n");
}

//註冊
int Register() 
{
    flag = 0;
    system("clear");
    SendBuf.cmd = reg;
    char pass1[20] = {0};
    char pass2[20] = {0};

    printf("\t\t\t\t註冊中......\n");
    printf("\n\n");
    printf("\t\t\t\t請輸入你的使用者名稱:\n");
    printf("\t\t\t\t");
    scanf("\t\t\t\t%s", SendBuf.username);
    SCAN_N();
    printf("\t\t\t\t請輸入你的密碼:\n");
    printf("\t\t\t\t");
    scanf("\t\t\t\t%s", pass1);
    SCAN_N();
    printf("\t\t\t\t請確認你的密碼:\n");
    printf("\t\t\t\t");
    scanf("\t\t\t\t%s", pass2);
    SCAN_N();

    if(strcmp(pass1, pass2) != 0)  
    {  
        printf("\t\t\t\t密碼輸入不一致!請重新輸入密碼!\n");  
        printf("請在此重新輸入你的密碼:\n");
        scanf("%s",pass2);
    }
    else
    {
        strcpy(SendBuf.password, pass1);
    }
}

//登入
int Login() 
{
    system("clear");
    SendBuf.cmd = log_in;
    printf("\t\t\t\t登入中......\n");
    printf("\n\n");
    printf("\t\t\t\t請輸入你的賬號:\n");
    printf("\t\t\t\t");
    scanf("\t\t\t\t%s",SendBuf.username);
    SCAN_N();
    printf("\t\t\t\t請輸入你的密碼:\n");
    printf("\t\t\t\t");
    scanf("\t\t\t\t%s",SendBuf.password);

}


//處理登陸後的函式
int deal_login()                    
{
    if(out == 1)  
    {  
        out--;  
        return Exit;   
    }  

    char choice2[10] = {0};
    char file[2048] = {0};
    char filename[50] ={0};
    int fd;

    while(1)
    {
        chatshow();

        scanf("%s",choice2);

        switch(choice2[0])
        {
            case 'a':   //私聊  
            {
                system("clear");  

                if(flag == 23)
                {
                    printf("\n\t\t\t\t您已經被禁言了!\n");
                    sleep(2);
                    break;
                }

                printf("\t\t\t\t請輸入對方的名字:\n");
                printf("\t\t\t\t");
                scanf("%s", SendBuf.toname);  
                SCAN_N();  

                printf("\t\t\t\t請輸入您想要說的話:\n");
                printf("\t\t\t\t");
                scanf("%s", SendBuf.message);  
                SCAN_N();  

                SendBuf.cmd = private_chat;  

                strcpy(SendBuf.username,name);

                if(strcmp(SendBuf.toname, name) ==0)  
                {  
                    sleep(1);  
                    system("clear");  
                    printf("\t\t\t\t不可以給自己發信息!\n");  
                    printf("\t\t\t\t請重新輸入使用者名稱!\n");
                    break;  
                } 

                ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
                if (ret < 0)
                {
                    perror("sendto_pchat");
                    exit(1);
                }  

                sprintf(filename, "%s chat with %s.txt", name, SendBuf.toname);  
                fd = open(filename, O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR);  
                if(fd == -1)  
                {  
                    perror("open");  
                    exit(1);  
                }  

                sprintf(file, "%s 給 %s 傳送了一條訊息:%s", name, SendBuf.toname, SendBuf.message);  
                ret = write(fd, file, strlen(file));  
                if(ret == -1)  
                {  
                    perror("write");  
                    exit(1);  
                }
                printf("\t\t\t\t傳送中...\n");  
                sleep(2);  

                break;  
            }

            case 'b'://群聊
                {
                    system("clear");

                    if(flag == 23)
                    {
                        printf("\n\t\t\t\t您已經被禁言了!\n");
                        sleep(2);
                        break;
                    }

                    printf("\t\t\t\t請傳送訊息:\n");

                    scanf("%s", SendBuf.message);

                    SendBuf.cmd = group_chat;

                    strcpy(SendBuf.username,name);
                    ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
                    if (ret < 0)
                    {
                        perror("sendto_groupchat");
                        exit(1);
                    }
                    printf("\t\t\t\t傳送中......\n");
                    sleep(2);
                    break;
                }

            case 'c': //檢視線上人數
            {
                system("clear");
                SendBuf.cmd = online;
                ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
                if (ret < 0)
                {
                    perror("sendto_onlinenum");
                    exit(1);
                }
                sleep(1);
                break;
            }

            case 'd':  //群發表情
            {
                system("clear");

                if(flag == 23)
                {
                    printf("\n\t\t\t\t您已經被禁言了!\n