struct.h
#ifndef _STRUCT_H_//客户端头文件
#define _STRUCT_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sqlite3.h>
#define PORT 9999
sqlite3 * database;
char myName[20];
int flag = 123;
char tag[100];
struct Msg
{
int cmd; // 消息类型
char fromname[20];
char password[10];
char tag[50];
char toname[20];
char msg[1024]; // 消息内容
};
#endif
client.c
#include "struct.h"
void * readMsg(void *v)
{
int socketfd = (int)v;
struct Msg msg;
while (1)
{
read (socketfd, &msg, sizeof(msg));
switch (msg.cmd)
{
case 3001:
printf ("%s 给你发一条消息:%s\n", msg.fromname, msg.msg);
keepmsg(&msg);
break;
case 3002:
printf ("私发消息成功!\n");
break;
case 3003:
printf ("该用户不在线!\n");
break;
case 4001:
printf ("%s群发消息:%s\n",msg.fromname, msg.msg);
keepmsg(&msg);
break;
case 4002:
printf ("群发消息成功!\n");
break;
case 5001:
printf ("在线用户有:\n");
printf ("%s\n",msg.msg);
break;
case 6001:
printf ("修改密码失败!\n");
break;
case 6002:
printf ("修改密码成功!\n");
break;
case 6003:
printf ("密码错误!\n");
break;
case 7001:
printf ("修改个性签名失败!\n");
break;
case 7002:
printf ("修改个性签名成功!\n");
strcpy( tag, msg.tag );
break;
case 1301:
printf ("退出成功!\n");
sleep(1);
flag = 123;
break;
case 1302:
printf ("退出失败!\n");
break;
}
}
}
//注册
void reg(int socketfd)
{
struct Msg msg;
msg.cmd = 1;
char passwd[10];
printf ("请输入用户名:\n");
fgets(myName, 20, stdin);
strcpy (msg.fromname, myName);
printf ("请输入密码:\n");
fgets(passwd, 10, stdin);
strcpy (msg.password, passwd);
write (socketfd, &msg, sizeof(msg));
read (socketfd, &msg, sizeof(msg));
if (msg.cmd == 1001)
{
printf ("该用户已存在!\n");
}
else if (msg.cmd == 1002)
{
printf ("注册失败!\n");
}
else if (msg.cmd == 1003)
{
printf ("注册成功!\n");
}
sleep(1);
}
//登录
void login(int socketfd)
{
struct Msg msg;
msg.cmd = 2;
char passwd[10];
printf ("请输入用户名:\n");
fgets(myName, 20, stdin);
strcpy (msg.fromname, myName);
printf ("请输入密码:\n");
fgets(passwd, 10, stdin);
strcpy (msg.password, passwd);
write (socketfd, &msg, sizeof(msg));
read (socketfd, &msg, sizeof(msg));
if (msg.cmd == 2001)
{
printf ("该用户名不存在!\n");
}
else if (msg.cmd == 2002)
{
printf ("用户已在线!\n");
}
else if (msg.cmd == 2003)
{
printf ("用户登录成功!\n");
flag = 456;
strcpy( tag, msg.tag );
pthread_t id;
pthread_create(&id, NULL, readMsg, (void *)socketfd);
pthread_detach(id); // 线程分离
}
else if (msg.cmd == 2004)
{
printf ("密码错误!\n");
}
sleep(1);
}
//私聊
void priva(int socketfd)
{
struct Msg msg;
msg.cmd = 3;
printf ("请输入要发送的对象名称: \n");
fgets(msg.toname, 20, stdin);
printf ("请输入要发送的内容: \n");
fgets(msg.msg, 1024, stdin);
strcpy (msg.fromname, myName);
write (socketfd, &msg, sizeof(msg));
sleep(1);
}
//群聊
void group(int socketfd)
{
struct Msg msg;
msg.cmd = 4;
char buf[5] = "all";
strcpy( msg.toname, buf );
printf ("请输入要发送的内容: \n");
fgets(msg.msg, 1024, stdin);
write (socketfd, &msg, sizeof(msg));
sleep(1);
}
//查看在线用户
void check( int socketfd )
{
struct Msg msg;
msg.cmd = 5;
write (socketfd, &msg, sizeof(msg));
sleep(2);
}
//修改密码
void changepwd( int socketfd )
{
struct Msg msg;
msg.cmd = 6;
char passwd[10];
printf ("请输入你现在的密码:\n");
fgets (passwd, 10, stdin);
strcpy (msg.password, passwd);
printf ("请输入你想改成的密码:\n");
fgets (passwd, 10, stdin);
strcpy (msg.msg, passwd);
write (socketfd, &msg, sizeof(msg));
sleep(2);
}
//修改个性签名
void changetag( int socketfd )
{
struct Msg msg;
msg.cmd = 7;
char tag[50];
printf ("请输入你的个性签名:\n");
fgets (tag, 50, stdin);
strcpy (msg.tag, tag);
write (socketfd, &msg, sizeof(msg));
sleep(2);
}
//保存历史消息
int keepmsg( struct Msg *msg )
{
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char buf[100];
sprintf (buf, "insert into msg values('%s', '%s', '%s')", msg->fromname, msg->toname, msg->msg);
int ret = sqlite3_exec(database, buf, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败:%s\n", errmsg);
return -1;
}
}
//查看历史消息
int history()
{
char *errmsg = NULL;
char **resultp = NULL;
int nrow, ncolumn;
char *sql = "select * from msg";
int ret = sqlite3_get_table(database, sql, &resultp, &nrow, &ncolumn, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败:%s\n", errmsg);
return -1;
}
int i;
printf ("nrow = %d, ncolumn = %d\n", nrow, ncolumn);
for (i = 0; i < (nrow+1)*ncolumn; i++)
{
if (i % ncolumn == 0)
printf ("\n");
printf ("%-12s", resultp[i]);
}
printf ("\n");
sqlite3_free_table(resultp);
sleep(2);
}
//退出
void quit( int socketfd )
{
struct Msg msg;
msg.cmd = 13;
write (socketfd, &msg, sizeof(msg));
sleep(2);
}
void log_screen()
{
system("clear");
printf(" -------------------------------------- \n");
printf(" | | \n");
printf(" | 欢迎使用**聊天室 | \n");
printf(" | | \n");
printf(" | 1、注册; | \n");
printf(" | 2、登录; | \n");
printf(" | 3、退出; | \n");
printf(" | | \n");
printf(" | 请输入你的操作: | \n");
printf(" | | \n");
printf(" -------------------------------------- \n");
}
void user_screen()
{
system("clear");
printf("%s:%s\n",myName,tag);
printf("\t\t\n");
printf("\t\t\n");
printf("\t\t1、私聊;\n");
printf("\t\t2、群聊;\n");
printf("\t\t3、查看在线用户;\n");
printf("\t\t4、修改密码;\n");
printf("\t\t5、修改个性签名;\n");
printf("\t\t6、查看历史消息;\n");
printf("\t\t7、输入要发送文件的用户;\n");
printf("\t\t8、选择要发送的文件;\n");
printf("\t\tq、退出;\n");
printf("\t\t\n");
printf("\t\t\n");
printf("\t\t\n");
printf("\t\t 请输入你的操作:\n");
}
void super_screen()
{
system("clear");
printf("%s:%s\n",myName,tag);
printf("\t\t\n");
printf("\t\t\n");
printf("\t\t1、私聊;\n");
printf("\t\t2、群聊;\n");
printf("\t\t3、查看在线用户;\n");
printf("\t\t4、修改密码;\n");
printf("\t\t5、修改个性签名;\n");
printf("\t\t6、查看历史消息;\n");
printf("\t\t7、输入要发送文件的用户;\n");
printf("\t\t8、选择要发送的文件;\n");
printf("\t\ts、禁言;\n");
printf("\t\tl、解禁;\n");
printf("\t\tt、踢人;\n");
printf("\t\tq、退出;\n");
printf("\t\t\n");
printf("\t\t\n");
printf("\t\t\n");
printf("\t\t 请输入你的操作:\n");
}
// 客户端向服务器发送数据
void ask_server(int socketfd)
{
char ch[2];
while (flag == 123 )
{
log_screen();
fgets(ch, 2, stdin);
while(getchar()!= '\n');
switch(ch[0])
{
case '1': // 注册
reg(socketfd);
break;
case '2': // 登录
login(socketfd);
break;
case '3': // 退出
exit(0);
break;
}
system("clear");
}
while( flag == 456 )
{
user_screen();
fgets(ch, 2, stdin);
while(getchar()!= '\n');
switch(ch[0])
{
case '1': // 私聊
priva(socketfd);
break;
case '2': // 群聊
group(socketfd);
break;
case '3': // 查看在线用户
check(socketfd);
break;
case '4': // 修改密码
changepwd(socketfd);
break;
case '5': // 修改个性签名
changetag(socketfd);
break;
case '6': // 查看历史消息
history();
break;
case 'q':
quit(socketfd);
break;
}
system("clear");
}
}
int main()
{
// 创建与服务器通信的套接字
int socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1)
{
perror ("socket");
return -1;
}
// 连接服务器
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; // 设置地址族
addr.sin_port = htons(PORT); // 设置本地端口
inet_aton("127.0.0.1",&(addr.sin_addr));
// 连接服务器,如果成功,返回0,如果失败,返回-1
// 成功的情况下,可以通过socketfd与服务器进行通信
int ret = connect(socketfd, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1)
{
perror ("connect");
return -1;
}
printf ("成功连上服务器\n");
// 打开数据库
ret = sqlite3_open("msg.db", &database);
if (ret != SQLITE_OK)
{
printf ("打开数据库失败\n");
return -1;
}
printf ("打开数据库成功\n");
char *errmsg = NULL;
char *sql = "create table if not exists msg ( fromname TEXT, toname TEXT, msg TEXT )";
ret = sqlite3_exec(database, sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
printf ("数据库操作失败:%s\n", errmsg);
return -1;
}
ask_server(socketfd);
// 关闭套接字
close(socketfd);
return 0;
}