1、服务器
#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>
#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 SIZE 20 //账号密码的最大长度
typedef enum {FALSE,TRUE}BOOL;
// 创建,绑定端口和ip,监听套接字
int init();
// 通信套接字
int myAccept(int listen_socket);
//工作函数
void *handl_client(void *v);
//注册
void reg(int cmd,long client_socket);
//登录
BOOL login(int cmd,long client_socket);
int main()
{
int listen_socket = init();
if(-1 == listen_socket)
return -1;
while(1)
{
long client_socket = myAccept(listen_socket);
if(-1 == client_socket)
{
continue;
printf("dasdasdas\n");
}
//创建线程
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;
}
return client_socket;
}
//工作函数,处理客户端请求
void *handl_client(void *v)
{
long client_socket = (long)v;
while(1)
{
int cmd;
int ret = read(client_socket,&cmd,sizeof(int)); //判断请求
if(0 == ret)
{
printf("客户端退出\n");
break;
}
switch(cmd)
{
case REG: //注册
reg(cmd,client_socket);
break;
case LOGIN:
login(cmd,client_socket);
break;
}
}
}
//注册模块
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;
}
char *errmsg;
//设计数据库内容id,账号,密码
const char *sql = "create table if not exists mydata(name TEXT,passwd TEXT,primary key(name))";
sqlite3_exec(db, sql, NULL, NULL, &errmsg);
//读取客户端的数据部分
read(client_socket,&Data,sizeof(struct data));
//不存在,添加进数据库
char str[100];
int id = 1;
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;
}
write(client_socket,&Rep,sizeof(struct _rep));
}
//登录模块
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;
printf("%d\n",row);
printf("%d\n",column);
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;
}
}
write(client_socket,&Rep,sizeof(struct _rep));
if(Rep.result == LOG_ERR)
{
printf("账号或者密码错误\n");
return FALSE;
}
else if(Rep.result == LOG_OK)
{
printf("%s账号登录成功\n",Data.name);
return TRUE;
}
}
2、客户端
#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>
#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 SIZE 20 //账号密码的最大长度
typedef enum {FALSE,TRUE}BOOL;
//功能
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();
int main()
{
//创建套接字
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(PORT); /* 端口号 */
addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 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("1、登录聊天室\n");
printf("2、注册新账号\n");
printf("0、退出\n");
}
//功能选择
void func(int conn_socket)
{
while(1)
{
system("clear");
menu();
int i;
scanf("%d",&i);
switch(i)
{
case 2:
Reg(conn_socket);
break;
case 1:
int tmp = Login(conn_socket);
if(tmp == TRUE)
Online(conn_socket);
break;
case 0:
printf("程序已经退出\n");
break;
default :
printf("无效指令\n");
break;
}
if(0 == i)
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));
//接收服务器反馈信息
printf("正在等待账号注册\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)
{
printf("注册成功\n");
}
else if(Rep.cmd == REG && Rep.result == RES_ERR)
{
printf("账号已经存在,注册失败\n");
}
}
//登录
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));
//接收服务器反馈信息
printf("账号登录中....\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");
printf("登录成功\n");
sleep(1);
return TRUE;
}
else if(Rep.cmd == LOGIN && Rep.result == LOG_ERR)
{
system("clear");
printf("账号或密码错误\n");
sleep(1);
return FALSE;
}
}
//在线界面
void menu_online()
{
printf("1、查看在线用户\n");
printf("2、进入群聊\n");
printf("3、进入私聊\n");
printf("4、查看聊天记录\n");
printf("5、更改用户密码\n");
printf("6、在线注销当前用户\n");
printf("0、退出登录\n");
}
//在线
void Online(int conn_socket)
{
}