由于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");
sleep(2);
break;
}
char choice3[10]={0};
SendBuf.cmd = face;
printf("\t\t\t\t**************************\n");
printf("\t\t\t\t1 感动 ≧◇≦ \n");
printf("\t\t\t\t2 无奈 ╮( ̄▽  ̄)╭\n");
printf("\t\t\t\t3 哭泣 T_T\n");
printf("\t\t\t\t4 惊讶 ⊙?⊙\n");
printf("\t\t\t\t5 喵 (= ̄ω ̄=)\n");
printf("\t\t\t\t6 害羞 (# ̄▽ ̄#)\n");
printf("\t\t\t\t请输入你的选择\n");
scanf("%s",choice3);
SendBuf.p_f = choice3[0];
strcpy(SendBuf.username,name);
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_face");
exit(1);
}
printf("\t\t\t\t发送中......\n");
sleep(2);
break;
}
case 'e': //发送常用语
{
system("clear");
if(flag == 23)
{
printf("\n\t\t\t\t您已经被禁言了!\n");
sleep(2);
break;
}
char choice4[10]={0};
printf("\t\t\t\t请输入对方的名字:\n");
printf("\t\t\t\t");
scanf("%s", SendBuf.toname);
strcpy(SendBuf.username,name);
SendBuf.cmd = send_useful;
printf("\t\t\t\t**************************\n");
printf("\t\t\t\t1 I see. 我明白了.\n");
printf("\t\t\t\t2 My god! 天哪!\n");
printf("\t\t\t\t3 No way! 不行!\n");
printf("\t\t\t\t4 Cheer up! 振作起来!\n");
printf("\t\t\t\t5 Good job! 做得好!\n");
printf("\t\t\t\t6 Bless you! 祝福你!\n");
printf("\t\t\t\t7 Thank you! 谢谢!\n");
printf("\n\t\t\t请输入你想发送的常用语:\n");
scanf("%s",choice4);
SCAN_N();
SendBuf.p_u = choice4[0];
if(strcmp(name,SendBuf.toname)==0)
{
sleep(1);
system("clear");
printf("\t\t\t\t不可以给自己发送常用语");
printf("\t\t\t\t请重新输入用户名!\n");
return -1;
}
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_useful");
exit(1);
}
printf("\n\t\t\t正在发送...\n");
sleep(2);
break;
}
case 'f': //开通会员
{
system("clear");
if(SendBuf.vip == 0)
{
char a[2];
system("clear");
printf("\n\n\n\t\t\t\t您确定要支付十万块成为会员吗?\n");
printf("\n\t\t\t\t您确认支付吗?(y/n)");
scanf("%s",a);
if(a[0] == 'y')
{
strcpy(SendBuf.username,name);
SendBuf.vip = 1;
SendBuf.cmd = Vip;
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_vip");
exit(1);
}
printf("\n\n\t\t请稍等...\n");
sleep(2);
}
else
{
break;
}
}
else if(SendBuf.vip == 1)
{
printf("您已经是会员了,无需再次开通!\n");
}
break;
}
case 'g': //禁言
{
if(SendBuf.vip == 1)
{
system("clear");
printf("请选择您想要禁言的人:\n");
scanf("%s",SendBuf.toname);
SendBuf.cmd = shutup;
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_shutup1");
exit(1);
}
printf("\n\n\t\t请稍等...\n");
sleep(2);
}
else if(SendBuf.vip == 0)
{
printf("您需要开通会员才能禁言别人哦!\n");
}
break;
}
case 'h': //踢人
{
if(SendBuf.vip == 1)
{
system("clear");
printf("请选择您想要让他下线的人:\n");
scanf("%s",SendBuf.toname);
SendBuf.cmd = kick;
strcpy(SendBuf.username,name);
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_kick1");
exit(1);
}
printf("\n\n\t\t请稍等...\n");
sleep(2);
}
else if(SendBuf.vip == 0)
{
printf("您需要开通会员才能让别人下线哦!");
}
break;
}
case 'i': //查看聊天记录
{
system("clear");
char n[20];
char filename1[50];
char file1[2048];
char kl;
int fd1;
int i = 0;
printf("\n\n\n\n\n\n\t\t\t\t您想看和谁的聊天记录呢?\n");
scanf("%s",n);
SCAN_N();
sprintf(filename1, "%s chat with %s.txt", name, n);
fd1 = open(filename1,O_RDONLY,S_IRUSR | S_IWUSR);
if(fd1 == -1)
{
system("clear");
printf("\n\n\n\n\n\n\n\t\t\t\t您与%s还没有聊天记录!\n",n);
break;
}
while(1)
{
memset(&kl, 0, sizeof(kl));
ssize_t read_bytes = read(fd1, &kl, sizeof(kl));
if(read_bytes == -1)
{
perror("read");
return -1;
}
if(read_bytes == 0)
{
break;
}
file1[i] = kl;
i++;
}
file1[i] = '\0';
printf("\n%s\n", file1);
break;
}
case 'j': //文件传输
{
int ret;
FILE *fp;
printf("接收方用户名:\n");
scanf("%s", SendBuf.toname);
SCAN_N();
if (!strcmp(SendBuf.toname, name))
{
printf("不要发文件给自己哦!\n");
printf("\t\t\t\t请重新输入用户名!\n");
break;
}
strcpy(SendBuf.username, name);
printf("请选择文件:\n");
scanf("%s", SendBuf.file_name);
SendBuf.cmd = send_file;
fp = fopen(SendBuf.file_name, "r");
if (NULL == fp)
{
printf("无法打开,该文件不存在!\n");
return;
}
ret = fread(SendBuf.file_content, 1, sizeof(SendBuf.file_content), fp);
if (0 == ret)
{
perror("fread_file_transfer");
return;
}
fclose(fp);
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_file");
return;
}
sleep(2);
}
break;
case 'k': //解禁
{
char x[2];
if(flag == 0)
{
system("clear");
printf("\n\n\n\t\t\t\t您没有被禁言!\n");
}
else if(flag == 23)
{
if(SendBuf.vip == 0)
{
system("clear");
printf("\n\n\n\n\t\t\t\t您还没有开通会员,请先开通会员!\n");
}
else if(SendBuf.vip == 1)
{
system("clear");
printf("\n\n\n\n\t\t\t\t您想现在解禁吗!(y/n)\n");
scanf("%s",x);
SCAN_N();
if(x[0] == 'y')
{
flag = 0;
system("clear");
printf("\n\n\n\t\t\t\t恭喜您成功解禁!\n");
}
}
}
break;
}
case 'z': //下线
{
system("clear");
SendBuf.cmd = quit;
strcpy(SendBuf.username,name);
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_quit1");
exit(1);
}
sleep(1);
return Exit;
}
case 'q':
return Exit;
default:
system("clear");
printf("\n\n\n\n");
printf("\n\n\t\t请输入a--z之间的选择!\n");
sleep(2);
break;
}
}
}
//接收服务器发送的结果的接口函数
void *Recv_Server(void *arg)
{
char q;
int i;
int length = sizeof(server_addr);
while(1)
{
ret = recvfrom(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&server_addr, &length);
if (ret < 0)
{
perror("recvfrom");
exit(1);
}
switch(RecvBuf.result)
{
case(private_chat):
{
printf("\t\t\t\t%s 给你发了一条消息:%s\n",RecvBuf.fromname,RecvBuf.message);
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(Send_success):
{
system("clear");
printf("\t\t\t\t发送成功\n");
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(Send_failure):
{
system("clear");
printf("\t\t\t\t发送失败,对方不在线\n");
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(Pchat_failure):
{
system("clear");
printf("\t\t\t\t对不起,对方不在线!\n");
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(group_chat):
{
printf("\t\t\t\t%s 群发了一条消息:%s\n",RecvBuf.fromname,RecvBuf.message);
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(Gchat_failure):
{
system("clear");
printf("\t\t\t\t群聊失败!\n");
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(online):
{
system("clear");
printf("\t\t\t\t当前在线好友人数: %d\n",RecvBuf.num);
for(i = 0 ; i < RecvBuf.num ; i++)
{
printf("\t\t\t\t%s\n",RecvBuf.online_name[i]);
}
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case(face):
{
char emoj1[20] = {0};
switch(RecvBuf.p_f)
{
case '1':
{
strcpy(emoj1,"感动 ≧◇≦");
printf("\t\t\t\t%s 给大家发了一个表情:%s\n",RecvBuf.fromname,emoj1);
break;
}
case '2':
{
strcpy(emoj1,"无奈 ╮( ̄▽  ̄)╭");
printf("\t\t\t\t%s 给大家发了一个表情:%s\n",RecvBuf.fromname,emoj1);
break;
}
case '3':
{
strcpy(emoj1,"哭泣 T_T");
printf("\t\t\t\t%s 给大家发了一个表情:%s\n",RecvBuf.fromname,emoj1);
break;
}
case '4':
{
strcpy(emoj1,"惊讶 ⊙?⊙");
printf("\t\t\t\t%s 给大家发了一个表情:%s\n",RecvBuf.fromname,emoj1);
break;
}
case '5':
{
strcpy(emoj1,"喵 (= ̄ω ̄=)");
printf("\t\t\t\t%s 给大家发了一个表情:%s\n",RecvBuf.fromname,emoj1);
break;
}
case '6':
{
strcpy(emoj1,"害羞 (# ̄▽ ̄#)");
printf("\t\t\t\t%s 给大家发了一个表情:%s\n",RecvBuf.fromname,emoj1);
break;
}
}
break;
}
case(face_failure):
{
system("clear");
printf("发送失败,没有该表情!\n");
sleep(2);
memset(&RecvBuf.result,0,sizeof(RecvBuf.result));
break;
}
case (send_useful):
{
char ue[50];
switch (RecvBuf.p_u)
{
case '1':
strcpy(ue,"I see. 我明白了.");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
case '2':
strcpy(ue,"My god! 天哪!");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
case '3':
strcpy(ue,"3 No way! 不行!");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
case '4':
strcpy(ue,"Cheer up! 振作起来!");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
case '5':
strcpy(ue,"Good job! 做得好!");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
case '6':
strcpy(ue,"Bless you! 祝福你!");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
case '7':
strcpy(ue,"Thank you! 谢谢!");
printf("\t\t\t\t%s给你发送了一句常用语:%s\n",RecvBuf.fromname,ue);
break;
}
break;
}
case(vip_success):
{
printf("\t\t\t\t恭喜您成功开通会员\n");
sleep(2);
break;
}
case(shutup):
{
flag = 23;
printf("\t\t\t\t%s已经把您禁言了!\n",RecvBuf.fromname);
break;
}
case(shutup_success):
{
printf("\t\t\t\t禁言成功!\n");
sleep(2);
break;
}
case(shutup_failure):
{
printf("\t\t\t\t对方不在线,禁言失败!\n");
break;
}
case(kick):
{
out = 1;
printf("\t\t\t\t您已经被%s踢出了聊天室,请重新登录!\n",RecvBuf.fromname);
printf("\t\t\t\t输入q返回!\n");
break;
}
case(kick_success):
{
printf("\t\t\t\t踢人成功!\n");
sleep(2);
break;
}
case(kick_failure):
{
printf("\t\t\t\t对方不在线,踢人失败!\n");
break;
}
case(quit):
{
system("clear");
printf("您已经成功下线!\n");
sleep(2);
break;
}
case(accept_file):
{
int ret;
FILE *fp1;
char file_name[64] = "文件";
strcat(file_name, RecvBuf.file_name);
fp1 = fopen(file_name, "w");
if (NULL == fp1)
{
perror("fopen") ;
return;
}
ret = fwrite(RecvBuf.file_content, 1, strlen(RecvBuf.file_content), fp1);
if (0 == ret)
{
perror("frite");
return;
}
printf("%s 给您发送文件,恭喜您已成功接收......\n", RecvBuf.fromname);
printf("文件名:%s\n", RecvBuf.file_name);
fclose(fp1);
break;
}
}
}
}
int main()
{
int length = sizeof(server_addr);
char choice[10]={0};
pthread_t tid;
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("sockt");
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = PORT;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
welcome();
while(1)
{
show();
scanf("%s",choice);
switch(atoi(&choice[0]))
{
case 1: //注册
{
if(Register() == -12)
{
break;
}
else
{
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_register");
exit(1);
}
bzero(&SendBuf, sizeof(SendBuf));
ret = recvfrom(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&server_addr, &length);
if (ret < 0)
{
perror("recvfrom_register");
exit(1);
}
if(RecvBuf.result == reg_success)
{
printf("\n\n\t\t\t\t恭喜您注册成功!\n");
}
else if(RecvBuf.result == existing)
{
printf("\n\n\t\t\t\t该账户已被注册!请重新注册!\n");
}
sleep(2);
break;
}
}
case 2: //登录
{
if (Login() == -14)
{
break;
}
else
{
ret = sendto(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("sendto_login");
exit(1);
}
bzero(&SendBuf, sizeof(SendBuf));
ret = recvfrom(sockfd, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, &length);
if (ret < 0)
{
perror("recvfrom_login");
exit(1);
}
if(SendBuf.result == log_success)
{
printf("\n\n\t\t\t\t恭喜你登录成功!\n");
strcpy(name,SendBuf.username);
sleep(2);
ret = pthread_create(&tid, NULL, (void *)Recv_Server, (void *)&sockfd); //起一个线程专门用来接收服务器发送给客户端的结果反馈
if (ret < 0)
{
perror("pthread_create");
exit(1);
}
pthread_detach(tid);
ret = deal_login();
if(ret == Exit)
{
break;
}
}
else if(SendBuf.result == logged)
{
printf("\n\n\t\t\t\t账号已登录!\n");
}
else if(SendBuf.result == log_error)
{
printf("\n\n\t\t\t\t账号或密码错误,请重新登录!\n");
}
}
break;
}
case 3:
{
bye();
system("clear");
exit(1);
break;
}
default :
{
system("clear");
printf("\n\n\n\n");
printf("\n\n\t\t请输入1--3之间的选择!\n");
sleep(2);
break;
}
}
}
return 0;
}