一、服务器代码
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#define PORT 9999 //端口号
#define REG 6000 //表示注册请求
#define RES_OK 6001 //成功注册
#define RES_ERR 6002 //注册失败
#define LOGIN 6003 //表示登录请求
#define LOG_OK 6004 //登录成功
#define LOG_ERR 6005 //登录失败,密码或者账号错误
#define LOG_NO 6006 //已经登录了
#define WHISPER 6008 //表示私聊请求
#define PER_OK 6009 //私聊成功
#define PER_ERR 6010 //用户不存在
#define MYSELF 6011 //用户本身
#define OTHER 6012 //其他用户
#define NUM 6013 //人数
#define SIZE 20 //账号密码的最大长度
#define EXIT 6014 //登出
#define TALK 6015 //群聊
#define REMOVE 6016 //注销
#define REVEISE 6017 //修改密码
#define OK 6018 //修改成功
#define NO 6019 //修改失败
#define LOOK 6020 //查看记录
typedef enum {FALSE,TRUE}BOOL;
// 创建,绑定端口和ip,监听套接字
int init();
// 通信套接字
int myAccept(int listen_socket);
//创建库
void cerat_k();
//工作函数
void *handl_client(void *v);
//注册
void reg(int cmd,long client_socket);
//登录
BOOL login(int cmd,long client_socket);
//私聊
void whisper(int cmd,long client_socket);
//群聊
void talk(int cmd,long client_socket);
//在线人数
void num(int cmd,long client_socket);
//退出
void leave(int cmd,long client_socket);
//注销
void Remove(int cmd,long client_socket);
//修改密码
void reveise(int cmd,long client_socket);
//查看记录
void Look_my(int cmd,long client_socket);
int count; //在线人数
int main()
{
cerat_k();
int listen_socket = init();
if(-1 == listen_socket)
return -1;
while(1)
{
long client_socket = myAccept(listen_socket);
if(-1 == client_socket)
{
continue;
}
//创建线程
pthread_t thread;
pthread_create(&thread,NULL,handl_client,(void *)client_socket);
pthread_detach(thread);
}
close(listen_socket);
return 0;
}
// 创建,绑定端口和ip,监听套接字
int init()
{
int listen_socket = socket(AF_INET, SOCK_STREAM, 0); //创建
if(-1 == listen_socket)
{
perror("创建套接字失败");
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; /* Internet地址族 */
addr.sin_port = htons(PORT); /* 端口号 */
addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址, 绑定本地的所有ip地址*/
int ret = bind(listen_socket, (const struct sockaddr *)&addr, sizeof(addr)); //绑定
if(-1 == ret)
{
perror("绑定失败");
return -1;
}
ret = listen(listen_socket, 5); // 监听套接字
if(-1 == ret)
{
perror("监听失败");
return -1;
}
return listen_socket;
}
// 通信套接字
int myAccept(int listen_socket)
{
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
printf("等待用户连接\n");
int client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &len);
if (-1 == client_socket)
{
perror("连接失败");
return -1;
}
printf ("连接成功\n");
printf ("客户端的 ip = %s, 端口 = %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
return client_socket;
}
//创建库
void cerat_k()
{
//创建信息数据库
sqlite3 *db1;
int ret = sqlite3_open("mydata.db",&db1);
if (ret != SQLITE_OK)
{
printf ("mydata数据库打开失败\n");
}
char *errmsg;
const char *sql = "create table if not exists mydata(name TEXT,passwd TEXT,primary key(name))";
sqlite3_exec(db1, sql, NULL, NULL, &errmsg);
//创建在线数据库
sqlite3 *db2;
ret = sqlite3_open("online.db",&db2);
if (ret != SQLITE_OK)
{
printf ("onlinr数据库打开失败\n");
}
const char *sq2 = "create table if not exists online(name TEXT,socket INTEGER,primary key(name))";
sqlite3_exec(db2, sq2, NULL, NULL, &errmsg);
//创建聊天库
sqlite3 *db3;
ret = sqlite3_open("chat.db",&db3);
if (ret != SQLITE_OK)
{
printf ("chat数据库打开失败\n");
}
const char *sq3 = "create table if not exists chat(ID INTEGER,sendname TEXT,content TEXT,recename TEXT,primary key(ID))";
sqlite3_exec(db3, sq3, NULL, NULL, &errmsg);
//防止服务器意外退出
char buf[100];
sprintf(buf ,"delete from online");
ret = sqlite3_exec(db2, buf, NULL, NULL, &errmsg );
if(ret != SQLITE_OK)
{
printf ("%s\n",errmsg);
}
sqlite3_close( db1 );
sqlite3_close( db2 );
sqlite3_close( db3 );
}
//工作函数,处理客户端请求
void *handl_client(void *v)
{
long client_socket = (long)v;
int tmp = FALSE;
while(1)
{
int cmd;
int ret = read(client_socket,&cmd,sizeof(int)); //判断请求
if(0 == ret)
{
printf("客户端退出\n");
break;
}
switch(cmd)
{
case REG: //注册
printf("请求注册\n");
reg(cmd,client_socket);
break;
case LOGIN: //登录
printf("请求登录\n");
tmp = login(cmd,client_socket);
break;
case WHISPER : //私聊
if(tmp == TRUE)
{
printf("进入私聊\n");
whisper(cmd,client_socket);
}
break;
case NUM: //在线人数
if(tmp == TRUE)
{
printf("查看当前人数\n");
num(cmd,client_socket);
}
break;
case EXIT: //下线
if(tmp == TRUE)
{
printf("请求下线\n");
leave(cmd,client_socket);
}
break;
case TALK: //群聊
if(tmp == TRUE)
{
printf("进入群聊\n");
talk(cmd,client_socket);
}
break;
case REMOVE:
if(tmp == TRUE)
{
printf("注销\n");
Remove(cmd,client_socket);
}
break;
case REVEISE:
if(tmp == TRUE)
{
printf("修改密码\n");
reveise(cmd,client_socket);
}
break;
case LOOK:
if(tmp == TRUE)
{
printf("查找记录\n");
Look_my(cmd,client_socket);
}
}
}
}
//注册模块
void reg(int cmd,long client_socket)
{
//注册协议:客户端--->服务器
struct data
{
char name[SIZE]; //账号
char passwd[SIZE]; //密码
}Data;
//注册协议:服务器--->客户端
struct _rep
{
int cmd; //对什么请求反馈
int result; //处理结果
}Rep = {cmd,RES_OK};
sqlite3 *db;
//打开数据库
int ret = sqlite3_open("mydata.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
Rep.result = RES_ERR;
}
//读取客户端的数据部分
read(client_socket,&Data,sizeof(struct data));
//不存在,添加进数据库
char *errmsg;
char str[100];
sprintf (str, "insert into mydata values('%s','%s')",Data.name,Data.passwd);
ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
if (ret != SQLITE_OK)
{
sqlite3_free(errmsg);
printf("数据已经存在\n");
Rep.result = RES_ERR;
}
else
printf("注册成功,账号为:%s,密码为%s\n",Data.name,Data.passwd);
write(client_socket,&Rep,sizeof(struct _rep));
sqlite3_close( db );
}
//登录模块
BOOL login(int cmd,long client_socket)
{
//登录协议:客户端--->服务器
struct data
{
char name[SIZE]; //账号
char passwd[SIZE]; //密码
}Data;
//登录协议:服务器--->客户端
struct _rep
{
int cmd; //对什么请求反馈
int result; //处理结果
}Rep = {cmd,LOG_ERR};
//打开数据库
sqlite3 *db;
int ret = sqlite3_open("mydata.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
return FALSE;
}
//读取客户端的数据部分
read(client_socket,&Data,sizeof(struct data));
//进行查找
char *errmsg;
const char *sql = "select * from mydata";
char **value = NULL;
int row;
int column;
ret = sqlite3_get_table(db, sql, &value, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
printf ("查询失败: %s\n", errmsg);
sqlite3_free(errmsg);
Rep.result = LOG_ERR;
return;
}
int i;
for (i = column; i < (row*column+column); i+=column)
{
if(0 == strcmp(value[i],Data.name) && 0 == strcmp(value[i+1],Data.passwd))
{
Rep.result = LOG_OK;
break;
}
}
if(Rep.result == LOG_ERR)
{
write(client_socket,&Rep,sizeof(struct _rep));
printf("账号或者密码错误\n");
return FALSE;
}
else if(Rep.result == LOG_OK)
{
//打开数据库
sqlite3 *db2;
int ret = sqlite3_open("online.db",&db2);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
Rep.result = LOG_ERR;;
}
//添加在线用户
char str[100];
sprintf (str, "insert into online values('%s',%ld)",Data.name,client_socket);
ret = sqlite3_exec(db2, str, NULL, NULL, &errmsg );
if (ret != SQLITE_OK)
{
sqlite3_free(errmsg);
Rep.result = LOG_NO;
printf("%s账号已经登录\n",Data.name);
write(client_socket,&Rep,sizeof(struct _rep));
sqlite3_close( db2 );
sqlite3_close( db );
return FALSE;
}
write(client_socket,&Rep,sizeof(struct _rep));
printf("%s账号登录成功\n",Data.name);
count++;
sqlite3_close( db2 );
sqlite3_close( db );
return TRUE;
}
}
//私聊
void whisper(int cmd,long client_socket)
{
//私聊协议:客户端--->服务器
struct data
{
char from_name[SIZE]; //发送方
char content[1024]; //发送内容
char to_name[SIZE]; //对象
}Data;
//私聊协议:服务器--->客户端
//给接收方的协议
struct content
{
int cmd; //对什么请求反馈
char content[1024]; //接收内容
int result; //处理结果
char name[SIZE]; //发送人名字
};
struct content CON;
CON.cmd = cmd;
CON.result = PER_ERR;
//读取客户端的数据部分
read(client_socket,&Data,sizeof(struct data));
//打开在线数据库
sqlite3 *db;
int ret = sqlite3_open("online.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//进行查找
char *errmsg;
const char *sql = "select * from online";
char **value = NULL;
int row;
int column;
ret = sqlite3_get_table(db, sql, &value, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
printf ("查询失败: %s\n", errmsg);
sqlite3_free(errmsg);
write(client_socket,&CON,sizeof(struct content));
return;
}
int i;
for (i = column; i < (row*column+column); i+=column)
{
if(0 == strcmp(value[i],Data.to_name)) //查看对方是否在线
{
if(atol(value[i+1]) == client_socket) //查看是否是自己
{
printf("value[i+1] = %d\n",atoi(value[i+1]));
printf("client_socket = %ld\n",client_socket);
printf("给自己发送信息\n");
break;
}
//打开记录数据库
sqlite3 *db;
int ret = sqlite3_open("chat.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//添加数据
char *errmsg;
char str[100];
sprintf (str, "insert into chat values(NULL,'%s','%s','%s')",Data.from_name,Data.content,Data.to_name);
ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
if (ret != SQLITE_OK)
{
sqlite3_free(errmsg);
}
printf("name = %s\n",Data.from_name);
strcpy(CON.name,Data.from_name);
strcpy(CON.content,Data.content); //获取接收信息
CON.result = OTHER;
write(atoi(value[i+1]),&CON,sizeof(struct content));
printf("%s给%s发送一条信息:\n",CON.name,Data.to_name);
printf("%s\n",CON.content);
CON.result = PER_OK;
break;
}
}
write(client_socket,&CON,sizeof(struct content));
sqlite3_close( db );
}
//群聊
void talk(int cmd,long client_socket)
{
//群聊协议:客户端--->服务器
struct data
{
char name[SIZE];
char content[1024]; //发送内容
}Data;
//群聊协议:服务器--->客户端
//给接收方的协议
struct content
{
int cmd; //对什么请求反馈
char name[SIZE];
char content[1024]; //接收内容
int result; //结果
}CON = {cmd};
//读取客户端的数据部分
read(client_socket,&Data,sizeof(struct data));
//打开数据库
sqlite3 *db;
int ret = sqlite3_open("online.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//进行查找
char *errmsg;
const char *sql = "select * from online";
char **value = NULL;
int row;
int column;
ret = sqlite3_get_table(db, sql, &value, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
printf ("查询失败: %s\n", errmsg);
sqlite3_free(errmsg);
write(client_socket,&CON,sizeof(struct content));
return;
}
int i;
for (i = column; i < (row*column+column); i+=column)
{
if(0 == strcmp(value[i],Data.name))
{
CON.result = MYSELF;
write(client_socket,&CON,sizeof(struct content));
}
else
{
//打开记录数据库
sqlite3 *db;
int ret = sqlite3_open("chat.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//添加数据
char *errmsg;
char str[100];
sprintf (str, "insert into chat values(NULL,'%s','%s','ALL')",Data.name,Data.content);
ret = sqlite3_exec(db, str, NULL, NULL, &errmsg );
if (ret != SQLITE_OK)
{
sqlite3_free(errmsg);
}
CON.result = OTHER;
strcpy(CON.name,Data.name);
strcpy(CON.content,Data.content);
write(atoi(value[i+1]),&CON,sizeof(struct content));
}
sqlite3_close( db );
}
printf("%s群发了一条信息:%s\n",CON.name,CON.content);
sqlite3_close( db );
}
//在线人数
void num(int cmd,long client_socket)
{
printf("--------------\n");
//服务器--->客户端协议
struct number
{
int cmd;
int count; //在线人数
}Num = {NUM,count};
printf("查看在线用户:%d\n",Num.count);
write(client_socket,&Num,sizeof(struct number));
}
//登出
void leave(int cmd,long client_socket)
{
struct _leave
{
char name[SIZE];
}Leave;
read(client_socket,&Leave,sizeof(struct _leave));
printf("%s\n",Leave.name);
sqlite3 *db;
int ret = sqlite3_open("online.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//进行登出
char *errmsg;
char buf[100];
sprintf(buf ,"delete from online where name = '%s'",Leave.name);
ret = sqlite3_exec(db, buf, NULL, NULL, &errmsg );
if(ret != SQLITE_OK)
{
printf ("%s\n",errmsg);
}
count--;
write(client_socket,&cmd,sizeof(cmd));
sqlite3_close( db );
}
//注销
void Remove(int cmd,long client_socket)
{
struct _remove
{
char name[SIZE];
}REmove;
read(client_socket,&REmove,sizeof(struct _remove));
sqlite3 *db;
int ret = sqlite3_open("mydata.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//进行查找
char *errmsg;
char buf[100];
sprintf(buf ,"delete from mydata where name = '%s'",REmove.name);
ret = sqlite3_exec(db, buf, NULL, NULL, &errmsg );
if(ret != SQLITE_OK)
{
printf ("%s\n",errmsg);
}
count--;
sqlite3 *db1;
ret = sqlite3_open("chat.db",&db1);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
sprintf(buf ,"delete from chat where sendname = '%s'",REmove.name);
ret = sqlite3_exec(db1, buf, NULL, NULL, &errmsg );
if(ret != SQLITE_OK)
{
printf ("%s\n",errmsg);
}
write(client_socket,&cmd,sizeof(cmd));
sqlite3_close( db );
sqlite3_close( db1 );
}
//修改密码
void reveise(int cmd,long client_socket)
{
//客户端--->服务器
struct _rev
{
char name[SIZE];
char old_passwd[SIZE];
char new_passwd[SIZE];
}REV;
//服务器--->客户端协议
struct _rev_to
{
int cmd;
int result;
}TO = {REVEISE,NO};
read(client_socket,&REV,sizeof(struct _rev));
sqlite3 *db;
int ret = sqlite3_open("mydata.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//进行修改
char *errmsg;
char buf[100];
sprintf(buf,"update mydata set passwd = '%s' where Name = '%s' and passwd = '%s';",REV.new_passwd,REV.name,REV.old_passwd);
ret = sqlite3_exec(db, buf, NULL, NULL, &errmsg );
if(ret != SQLITE_OK)
{
printf ("%s\n",errmsg);
}
//进行查找
const char *sq2 = "select * from mydata";
char **value = NULL;
int row;
int column;
ret = sqlite3_get_table(db, sq2, &value, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
printf ("查询失败: %s\n", errmsg);
sqlite3_free(errmsg);
return;
}
int i;
for (i = column; i < (row*column+column); i+=column)
{
if(0 == strcmp(value[i+1],REV.new_passwd))
{
TO.result = OK;
break;
}
}
if(TO.result == OK)
{
printf("%s修改密码成功\n",REV.name);
}
else if(TO.result == NO)
{
printf("修改密码失败\n");
}
write(client_socket,&TO,sizeof(struct _rev_to));
sqlite3_close( db );
}
//查看记录
void Look_my(int cmd,long client_socket)
{
//客户端--->服务器
struct _look
{
char name[SIZE];
}Look;
//服务器--->客户端
struct look_
{
int cmd;
char content[SIZE];
char to_name[SIZE];
}Look_ = {cmd};
read(client_socket,&Look,sizeof(struct _look));
//打开数据库
sqlite3 *db;
int ret = sqlite3_open("chat.db",&db);
if (ret != SQLITE_OK)
{
printf ("数据库打开失败\n");
}
//进行查找
char *errmsg;
const char *sql = "select * from chat";
char **value = NULL;
int row;
int column;
ret = sqlite3_get_table(db, sql, &value, &row, &column, &errmsg);
if (ret != SQLITE_OK)
{
printf ("查询失败: %s\n", errmsg);
sqlite3_free(errmsg);
return;
}
int i;
for (i = column; i < (row*column+column); i+=column)
{
printf("%s\n",value[i+1]);
printf("%s\n",Look.name);
if(0 == strcmp(value[i+1],Look.name))
{
strcpy(Look_.content,value[i+2]);
strcpy(Look_.to_name,value[i+3]);
printf("%s\n",Look_.content);
printf("%s\n",Look_.to_name);
write(client_socket,&Look_,sizeof(struct look_));
}
}
sqlite3_close( db );
}
二、客户端代码
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <time.h>
#include <stddef.h>
#define PORT 9999 //端口号
#define REG 6000 //表示注册请求
#define RES_OK 6001 //成功注册
#define RES_ERR 6002 //注册失败
#define LOGIN 6003 //表示登录请求
#define LOG_OK 6004 //登录成功
#define LOG_ERR 6005 //登录失败,密码或者账号错误
#define LOG_NO 6006 //已经登录了
#define WHISPER 6008 //表示私聊请求
#define PER_OK 6009 //私聊成功
#define PER_ERR 6010 //用户不存在
#define MYSELF 6011 //用户本身
#define OTHER 6012 //其他用户
#define NUM 6013 //人数
#define SIZE 20 //账号密码的最大长度
#define EXIT 6014 //登出
#define TALK 6015 //群聊
#define REMOVE 6016 //注销
#define REVEISE 6017 //修改密码
#define OK 6018 //修改成功
#define NO 6019 //修改失败
#define LOOK 6020 //查看记录
typedef enum {FALSE,TRUE}BOOL;
int tmp; //在线为1,不在线为0
char my_name[SIZE]; //本机账号
//功能
void func(int conn_socket);
//注册
void Reg(int conn_socket);
//主界面
void menu();
//登录
BOOL Login(int conn_socket);
//在线
void Online(int conn_socket);
//在线界面
void menu_online();
//私聊
void whisper(int conn_socket);
//群聊
void talk(int conn_socket);
//接收消息
void *ReadALL1(void *v);
void *ReadALL2(void *v);
//在线人数
void num(int conn_socket);
//登出
void leave(int conn_socket);
//注销
void Remove(int conn_socket);
//修改密码
void reveise(int conn_socket);
//查看记录
void Look_my(int conn_socket);
//时间记录
void Time()
{
time_t timer; //time_t就是long int 类型
struct tm* tblock;
timer = time(&timer); //这一句也可以改成time(&timer);
tblock = localtime(&timer);
printf("time is: %s\n",asctime(tblock));
}
//main函数
int main(int argc,char **argv)
{
//创建套接字
int conn_socket = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == conn_socket)
{
perror("创建套接字失败");
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; /* Internet地址族 */
addr.sin_port = htons(atoi(argv[2])); /* 端口号 */
addr.sin_addr.s_addr = inet_addr(argv[1]); /* IP地址, 绑定本地的所有ip地址*/
//连接客户端
int ret = connect(conn_socket, (const struct sockaddr *)&addr, sizeof(addr));
if(-1 == ret)
{
perror("绑定失败");
return -1;
}
func(conn_socket);
close(conn_socket);
return 0;
}
//主界面
void menu()
{
printf("--------------------------------\n");
printf("\t1、登录聊天室\n");
printf("\t2、注册新账号\n");
printf("\t0、退出\n");
printf("------------------------------\n");
}
//功能选择
void func(int conn_socket)
{
int tmp = FALSE;
while(1)
{
system("clear");
menu();
int i;
scanf("%d",&i);
switch(i)
{
case 2:
Reg(conn_socket);
break;
case 1:
tmp = Login(conn_socket);
if(tmp == TRUE)
Online(conn_socket);
break;
case 0:
if(0 == i)
system("clear");
printf("程序已经退出\n");
sleep(1);
return;
break;
default :
printf("无效指令\n");
break;
}
}
}
//注册
void Reg(int conn_socket)
{
struct data
{
const int cmd;
char name[SIZE]; //账号
char passwd[SIZE]; //密码
}Data ={REG};
struct _rep
{
int cmd; //对什么请求反馈
int result; //处理结果
}Rep;
//向服务器发送请求
printf("请输入注册账户:");
scanf("%s",Data.name);
printf("请输入注册密码:");
scanf("%s",Data.passwd);
write(conn_socket, &Data, sizeof(struct data));
//接收服务器反馈信息
system("clear");
printf("\t\t正在等待账号注册...\n");
sleep(1);
int ret = read(conn_socket, &Rep, sizeof(Rep));
if (-1 == ret)
{
perror ("read error");
}
if(Rep.cmd == REG && Rep.result == RES_OK)
{
system("clear");
printf("\t\t注册成功\n");
sleep(1);
}
else if(Rep.cmd == REG && Rep.result == RES_ERR)
{
system("clear");
printf("\t\t账号已经存在,注册失败\n");
sleep(1);
}
}
//登录
BOOL Login(int conn_socket)
{
//登录协议:客户端--->服务器
struct data
{
const int cmd;
char name[SIZE]; //账号
char passwd[SIZE]; //密码
}Data={LOGIN};
//登录协议:服务器--->客户端
struct _rep
{
int cmd; //对什么请求反馈
int result; //处理结果
}Rep;
printf("请输入账号:");
scanf("%s",Data.name);
printf("请输入密码:");
scanf("%s",Data.passwd);
//向服务器发送请求
write(conn_socket, &Data, sizeof(struct data));
//接收服务器反馈信息
system("clear");
printf("\t\t账号登录中....\n");
sleep(1);
int ret = read(conn_socket, &Rep, sizeof(Rep));
if (-1 == ret)
{
perror ("read error");
}
if(Rep.cmd == LOGIN && Rep.result == LOG_OK)
{
system("clear");
strcpy(my_name,Data.name);
tmp = 1;
printf("\t\t登录成功\n");
sleep(1);
return TRUE;
}
else if(Rep.cmd == LOGIN && Rep.result == LOG_ERR)
{
system("clear");
printf("\t\t账号或密码错误\n");
sleep(1);
return FALSE;
}
else if(Rep.cmd == LOGIN && Rep.result == LOG_NO)
{
system("clear");
printf("\t\t账号已经在线\n");
sleep(1);
return FALSE;
}
}
//在线界面
void menu_online()
{
printf("--------------------------------\n");
Time();
printf("\t1、查看在线用户\n");
printf("\t2、进入群聊\n");
printf("\t3、进入私聊\n");
printf("\t4、查看聊天记录\n");
printf("\t5、更改用户密码\n");
printf("\t6、在线注销当前用户\n");
printf("\t7、修改个性签名\n");
printf("\t8、发送文件\n");
printf("\t0、退出登录\n");
printf("--------------------------------\n");
}
//在线选择
void Online(int conn_socket)
{
long conn_socket1 = (long)conn_socket;
pthread_t thread2;
pthread_create(&thread2,NULL,ReadALL2,(void *)conn_socket1);
pthread_detach(thread2);
while(1)
{
system("clear");
int i;
menu_online();
printf("选择功能\n");
scanf("%d",&i);
switch(i)
{
case 3:
whisper(conn_socket);
break;
case 1:
num(conn_socket);
break;
case 0:
leave(conn_socket);
printf("%d\n",tmp);
if(tmp == FALSE)
{
return;
}
break;
case 2:
talk(conn_socket);
break;
case 6:
Remove(conn_socket);
leave(conn_socket);
if(tmp == FALSE)
{
return;
}
break;
case 5:
reveise(conn_socket);
sleep(1);
if(tmp == FALSE)
{
return;
}
break;
case 4:
Look_my(conn_socket);
break;
}
}
}
//私聊
void whisper(int conn_socket)
{
//私聊协议:客户端--->服务器
struct data
{
int cmd;
char from_name[SIZE];
char content[1024]; //发送内容
char to_name[SIZE]; //对象
};
struct data Data;
Data.cmd = WHISPER;
strcpy(Data.from_name,my_name);
printf("输入聊天对象 :");
scanf("%s",Data.to_name);
printf("输入聊天内容 :");
scanf("%s",Data.content);
write(conn_socket,&Data,sizeof(struct data));
}
//群聊
void talk(int conn_socket)
{
//群聊协议:客户端--->服务器
struct data
{
int cmd;
char name[SIZE];
char content[1024]; //发送内容
};
struct data Data;
Data.cmd = TALK;
strcpy(Data.name,my_name);
printf("输入聊天内容 :");
scanf("%s",Data.content);
write(conn_socket,&Data,sizeof(struct data));
}
//在线人数
void num(int conn_socket)
{
int cmd = NUM;
write(conn_socket,&cmd,sizeof(int));
printf("正在查看人数\n");
sleep(1);
}
//下线
void leave(int conn_socket)
{
struct _leave
{
int cmd;
char name[SIZE];
};
struct _leave Leave;
Leave.cmd = EXIT;
strcpy(Leave.name,my_name);
write(conn_socket,&Leave,sizeof(struct _leave));
printf("正在下线中...\n");
sleep(1);
}
//注销
void Remove(int conn_socket)
{
struct _remove
{
int cmd;
char name[SIZE];
};
struct _remove REmove;
REmove.cmd = REMOVE;
strcpy(REmove.name,my_name);
write(conn_socket,&REmove,sizeof(struct _remove));
printf("正在注销中...\n");
}
//修改密码
void reveise(int conn_socket)
{
struct _rev
{
int cmd;
char name[SIZE];
char old_passwd[SIZE];
char new_passwd[SIZE];
};
struct _rev REV;
REV.cmd = REVEISE;
strcpy(REV.name,my_name);
printf("请输入原密码:");
scanf("%s",REV.old_passwd);
printf("请输入新密码:");
scanf("%s",REV.new_passwd);
write(conn_socket,&REV,sizeof(struct _rev));
printf("正在修改...\n");
}
//查看记录
void Look_my(int conn_socket)
{
struct _look
{
int cmd;
char name[SIZE];
};
struct _look Look;
Look.cmd = LOOK;
strcpy(Look.name,my_name);
printf("%s\n",Look.name);
write(conn_socket,&Look,sizeof(struct _look));
}
//读数据----在线人数和下线
void *ReadALL2(void *v)
{
int cmd; //对什么请求反馈
int result; //结果
//私聊协议:服务器--->客户端
struct content
{
char content[1024]; //接收内容
int result; //处理结果
char name[SIZE]; //发送人名字
}CON;
//在线人数:服务器--->客户端协议
struct number
{
int count; //在线人数
}Num;
//群聊:服务器--->客户端
struct talking
{
char name[SIZE];
char content[1024]; //接收内容
int result; //结果
}talk_all;
//查看记录
struct look_
{
char content[SIZE];
char to_name[SIZE];
}Look_;
long conn_socket = (long)v;
while(1)
{
int cmd;
int ret = read(conn_socket,&cmd,sizeof(int)); //判断请求
switch(cmd)
{
case WHISPER : //私聊
ret = read(conn_socket,&CON,sizeof(struct content));
if(CON.result == PER_OK)
{
printf("发送消息成功\n");
sleep(1);
}
else if(CON.result == PER_ERR)
{
printf("发送消息失败\n");
sleep(1);
}
else if(CON.result == OTHER)
{
printf("%s给你发送一条信息:\n",CON.name);
printf("%s\n",CON.content);
sleep(1);
}
break;
case NUM:
ret = read(conn_socket,&Num,sizeof(struct number));
printf("当前有%d人在线\n",Num.count);
sleep(1);
break;
case EXIT:
tmp = 0;
printf("tmp = %d\n",tmp);
printf("下线成功\n");
sleep(1);
pthread_exit(NULL);
break;
case TALK:
ret = read(conn_socket,&talk_all,sizeof(struct talking));
if(talk_all.result == MYSELF)
{
printf("发送成功\n");
}
else if(talk_all.result == OTHER)
{
printf("%s群发:%s\n",talk_all.name,talk_all.content);
}
break;
case REMOVE :
tmp = 0;
printf("注销成功\n");
sleep(1);
break;
case REVEISE:
ret = read(conn_socket,&result,sizeof(int));
if(result == OK)
{
tmp = 0;
printf("修改密码成功\n");
leave(conn_socket);
}
else if(result == NO)
{
printf("密码错误,修改密码失败\n");
}
break;
case LOOK:
ret = read(conn_socket,&Look_,sizeof(struct look_));
printf("%s向%s发送信息为:%s\n",my_name,Look_.to_name,Look_.content);
break;
}
}
}