專案:聊天室(TCP select架構)(連結串列)—— 客戶端
阿新 • • 發佈:2019-01-20
標頭檔案:
#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");