服务器端:
/*********************************************************
- File name :chat.c
* ******************************************************/
#include "../../include/net.h"
int sayto_1(int sfd, Node *newnode)
{
char buf[100];
char *sql;
char *errmsg;
int nrow;
int ncolumn;
char **azresult;
/* 接收name,检查是否在线 */
memset(buf, 0, sizeof(buf));
sprintf(buf,"select * from client_inform where name = '%s' or id = '%s';",newnode->toname, newnode->toname);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("sqlite3_get_table error!\n");
exit(0);
}
if(nrow == 0) // 用户名不存在
{
newnode->ack = NOT_EXIT;
write(sfd, newnode, sizeof(Node));
return 0;
}
else if(nrow == 1) // 用户名存在
{
Online *temp = head;
while(temp != NULL)
{
if(temp->sfd == sfd) // 遍历在线用户,找出发送用户状态
{
strcpy(newnode->name, temp->name);
if(temp->speek_flag == 0) // 当前用户被禁言
{
newnode->ack = No_say;
write(sfd, newnode, sizeof(Node));
return 0;
}
}
temp = temp->next;
}
temp = head; // 当前用户没有被禁言
while(temp != NULL)
{
if(strcmp(newnode->toname, temp->name) == 0) // 遍历在线用户,找出toname sfd
{
newnode->ack = MSG_RECV_ONE;
write(temp->sfd, newnode, sizeof(Node));
return 0;
}
temp = temp->next;
}
/* 无其他在线用户 */
newnode->ack = No_online;
write(sfd, newnode, sizeof(Node));
}
return 0;
}
int sayall_1(int sfd, Node *newnode)
{
Online *temp = head;
while(temp != NULL)
{
if(temp->sfd == sfd)
{
strcpy(newnode->name, temp->name);
if(temp->speek_flag == 0)
{
newnode->ack = No_say;
write(sfd, newnode, sizeof(Node));
return 0;
}
}
temp = temp->next;
}
temp = head;
while(temp != NULL)
{
if(temp->sfd == sfd)
{
temp = temp->next;
continue;
}
newnode->ack = MSG_RECV_ALL;
write(temp->sfd, newnode, sizeof(Node));
temp = temp->next;
}
return 0;
}
int dis_1(int sfd, Node *newnode)
{
Online *temp = head;
while(temp != NULL)
{
if(temp->sfd == sfd)
{
temp = temp->next;
continue;
}
newnode->ack = DIS_NAME;
memset(newnode->name, 0, sizeof(Node));
strcpy(newnode->name, temp->name);
write(sfd, newnode, sizeof(Node));
temp = temp->next;
}
return 0;
}
int change_1(int sfd, Node *newnode)
{
int nrow;
int ncolumn;
char buf[100];
char *sql;
char *errmsg;
char **azresult;
Online *temp = head;
while(temp != NULL)
{
/* 根据sfd找出name */
if(temp->sfd == sfd)
{
strcpy(newnode->name, temp->name);
break;
}
temp = temp->next;
}
memset(buf, 0, sizeof(buf));
sprintf(buf,"select * from client_inform where name = '%s' and password = '%s';", newnode->name, newnode->password);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("sqlite3_get_table error!\n");
exit(0);
}
if(nrow == 0)
{
newnode->ack = PASSWD_ERR;
write(sfd, newnode, sizeof(Node));
}
else if(nrow == 1)
{
memset(buf, 0, sizeof(buf));
sprintf(buf,"UPDATE client_inform SET password = '%s' where password = '%s' and name = '%s';", newnode->msg, newnode->password, newnode->name);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("sqlite3_get_table error!\n");
exit(0);
}
newnode->ack = PASSWD_SUCCESS;
write(sfd, newnode, sizeof(Node));
}
return 0;
}
int send_1(int sfd, Node *newnode)
{
char buf[100];
char *sql;
char *errmsg;
int nrow;
int ncolumn;
char **azresult;
Online *temp = head;
while(temp != NULL)
{
/* 根据sfd找出name */
if(temp->sfd == sfd)
{
strcpy(newnode->name, temp->name);
break;
}
temp = temp->next;
}
/* 接受name,检查是否在线 */
memset(buf, 0, sizeof(buf));
sprintf(buf, "select * from client_inform where name = '%s' or id = '%s';", newnode->toname, newnode->toname);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("sqlite3_get_table send error!\n");
exit(0);
}
if(nrow == 0)
{
newnode->ack = NOT_EXIT;
write(sfd, newnode, sizeof(Node));
return 0;
}
else if(nrow == 1)
{
temp = head;
while(temp != NULL)
{
if(strcmp(newnode->toname, temp->name) == 0)
{
newnode->ack = RECV_FILE;
write(temp->sfd, newnode, sizeof(Node));
return 0;
}
temp = temp->next;
}
/* 无其他用户在线 */
newnode->ack = No_online;
write(sfd, newnode, sizeof(Node));
}
return 0;
}
/*********************************************************
- File name :creat_table.c
* ******************************************************/
#include "../../include/net.h"
int creat_table(sqlite3 *db)
{
char *sql;
char *errmsg;
sql = "create table if not exists client_inform(id varchar(10) primary key, name varchar(10), password varchar(10));";
if(SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg))
{
perror("sqlite3_exec error!\n");
exit(0);
}
return 0;
}
//int insert_record(sqlite3 *db)
//{
// char ch;
//char *sql;
// char *errmsg;
//}
/*********************************************************
- File name :get.c
* ******************************************************/
#include "../../include/net.h"
void get_id(Node *newnode)
{
int i = 0;
int j = 10000000;
long int id;
char buf[10] = {0};
srand(time(NULL));
id = (rand() & 100000000);
//printf("id = %ld\n",id);
while(id != 0)
{
buf[i++] = id / j + '0';
id = id % j;
j = j / 10;
}
buf[i] = '\0';
strcpy(newnode->id,buf);
//printf("newnode->id = %s\n",newnode->id);
}
Net.h:
/*********************************************************
- File name :net.h
* ******************************************************/
#ifndef NET_H_
#define NET_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sqlite3.h>
#include <pthread.h>
struct node
{
int ack;
char id[9];
char name[20];
char password[10];
char toname[20];
char msg[1024];
char file_name[100];
char file_msg[1024];
};
typedef struct node Node;
struct online
{
int sfd;
int on_flag;
int speek_flag;
char name[20];
struct online *next;
};
typedef struct online Online;
extern Online *head;
extern sqlite3 *db;
enum
{
reg = 0,
log,
sayto,
sayall,
dis,
change,
send_file,
stop_say,
let_say,
t_man,
quit = 10,
SUCCESS,
FAILE,
sup,
EXIT,
NOT_EXIT,
PASSWD_ERR,
SUCCESS_LOG,
REG_NOT_EXIT,
REG_EXIT,
SUCCESS_REG = 20,
No_say,
Ok_say,
MSG_RECV_ONE,
MSG_RECV_ALL,
DIS_NAME,
PASSWD_SUCCESS,
RECV_FILE,
STOP_SAY_OK,
NOT_STOP_SAY,
LET_SAY_OK = 30,
No_online,
T_OK,
YOU_OUT,
QUIT_OK
};
void read_msg(void *arg);
int change_1(int sfd, Node *newnode);
int dis_1(int sfd, Node *newnode);
void get_id(Node *newnode);
int let_say_1(int sfd, Node *newnode);
int log_1(int sfd, Node *newnode);
int reg_1(int sfd, Node *newnode);
int sayto_1(int sfd, Node *newnode);
int sayall_1(int sfd, Node *newnode);
int creat_table(sqlite3 *db);
int stop_say_1(int sfd, Node *newnode);
int tcp_init();
int t_man_1(int sfd, Node *newnode);
int quit_1(int sfd, Node *newnode);
int err_quit(int sfd);
int tcp_init();
int tcp_accept(int sfd);
#endif
/*********************************************************
- File name :log_reg.c
* ******************************************************/
#include "../../include/net.h"
int log_1(int sfd, Node *newnode)
{
char buf[100];
char *sql;
char *errmsg;
Online *linenode = (Online *) malloc (sizeof(Online));
/* 检查用户名是否存在 */
/* 超级用户 */
if((strcmp(newnode->id, "admin") == 0) && (strcmp(newnode->password, "admin") == 0))
{
newnode->ack = sup; // 发送ack = sup
printf("sup\n");
write(sfd, newnode, sizeof(Node));
return 0;
}
int i;
int nrow;
int ncolumn;
char **azresult = NULL;
memset(buf, 0, sizeof(buf));
sprintf(buf,"select * from client_inform where id = '%s' or name = '%s'",newnode->id, newnode->id);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("select id error!\n");
exit(0);
}
if(nrow == 0) //用户名不存在
{
newnode->ack = NOT_EXIT;
write(sfd, newnode, sizeof(Node));
return 0;
}
else if(nrow == 1) //用户名存在
{
/* 检查密码是否正确 */
memset(buf, 0, sizeof(buf));
sprintf(buf,"select * from client_inform where password = '%s' and (id = '%s' or name = '%s');", newnode->password, newnode->id, newnode->id);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("seletc password error!\n");
exit(0);
}
if(nrow == 0) //密码不正确
{
newnode->ack = PASSWD_ERR;
printf("perr\n");
write(sfd, newnode, sizeof(Node));
return 0;
}
else if(nrow == 1) //密码正确
{
Online *temp = head;
while(temp != NULL)
{
if(strcmp(temp->name,newnode->id) == 0)
{
if(temp->on_flag == 1)
{
newnode->ack = EXIT; //用户已在线
printf("exit\n");
write(sfd, newnode, sizeof(Node));
return 0;
}
}
temp = temp->next;
}
/* 登录信息正确,且用户不在线,保存在线信息 */
newnode->ack = SUCCESS_LOG; // 发送登录成功ack
write(sfd, newnode, sizeof(Node));
linenode->sfd = sfd; // 网络套接口
linenode->on_flag = 1; // 用户在线
linenode->speek_flag = 1; // 用户未被禁言
/* 若用户ID登录,改为昵称在线 */
memset(buf, 0, sizeof(buf));
sprintf(buf,"select * from client_inform where id = '%s';",newnode->id);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("select id error!\n");
exit(0);
}
if(nrow == 0) // 用户名登录
{
strcpy(linenode->name, newnode->id);
}
else if(nrow == 1) // ID登录
{
for(i = 0; i < (nrow + 1) * ncolumn; i++)
{
if(strcmp(azresult[i],newnode->id) == 0)
{
strcpy(linenode->name,azresult[i + 1]); // 用户在线昵称
break;
}
}
}
/* 头插 */
linenode->next = head;
head = linenode;
}
}
return 0;
}
int reg_1(int sfd, Node *newnode)
{
char buf[100];
char *sql;
char *errmsg;
/* 创建用户信息表 */
sql = "create table if not exists client_inform(id varchar(10),name varchar(10),password varchar(10));";
if(SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg))
{
perror("sqlite3_exec error!\n");
exit(0);
}
/* 检查name是否存在 */
int nrow;
int ncolumn;
char **azresult = NULL;
memset(buf, 0, sizeof(buf));
sprintf(buf,"select * from client_inform where name = '%s';",newnode->name);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("sqlite3_get_table error!\n");
exit(0);
}
/*
if(nrow == 0) //用户名不存在
{
newnode->ack = REG_NOT_EXIT;
write(sfd, newnode, sizeof(Node)); //发送用户名不存在
}
*/
if(nrow == 1) //用户名存在
{
newnode->ack = REG_EXIT;
write(sfd, newnode, sizeof(Node)); //发送用户名存在
return 0;
}
/* 用户名不存在,保存用户信息 */
get_id(newnode); // 生成ID
memset(buf, 0, sizeof(buf));
sprintf(buf,"insert into client_inform values('%s','%s','%s');",newnode->id, newnode->name, newnode->password);
sql = buf;
if(SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg))
{
perror("insert error!\n");
exit(0);
}
/* 发送注册成功信息 */
newnode->ack = SUCCESS_REG;
write(sfd, newnode, sizeof(Node));
return 0;
}
/*********************************************************
- File name :main.c
* ******************************************************/
#include "../../include/net.h"
sqlite3 *db = NULL;
Online *head = NULL;
int main(int argc, char **argv)
{
int rc;
int sfd;
int cfd;
pthread_t id;
sfd = tcp_init();
if(SQLITE_OK != (rc = sqlite3_open("user.db",&db)))
{
perror("sqlite3_open error!\n");
exit(0);
}
while(1)
{
cfd = tcp_accept(sfd);
pthread_create(&id, NULL, (void *)read_msg, (void *)&cfd);
}
close(sfd);
return 0;
}
/*********************************************************
- File name :quit_1.c
* ******************************************************/
#include "../../include/net.h"
int quit_1(int sfd, Node *newnode)
{
Online *temp = head;
Online *ptr;
if(sfd == temp->sfd)
{
head = head->next;
newnode->ack = QUIT_OK;
write(sfd, newnode, sizeof(Node));
temp->on_flag = 0;
ptr = temp;
temp = temp->next;
return 0;
}
while(temp != NULL)
{
if(sfd == temp->sfd)
{
newnode->ack = QUIT_OK;
write(sfd, newnode, sizeof(Node));
temp->on_flag = 0;
ptr->next = temp->next;
return 0;
}
ptr = temp;
temp = temp->next;
}
return 0;
}
int err_quit(int sfd)
{
Online *temp = head;
Online *ptr;
if(sfd == temp->sfd)
{
head = head->next;
temp->on_flag = 0;
ptr = temp;
temp = temp->next;
return 0;
}
while(temp != NULL)
{
if(sfd == temp->sfd)
{
temp->on_flag = 0;
ptr->next = temp->next;
return 0;
}
ptr = temp;
temp = temp->next;
}
return 0;
}
/*********************************************************
- File name :read_msg.c
* ******************************************************/
#include "../../include/net.h"
char buf[1024];
void read_msg(void *arg)
{
int sfd = *((int *)arg);
int n_read;
Node *newnode = (Node *) malloc (sizeof(Node));
while(1)
{
memset(newnode, 0, sizeof(Node));
/* 接收cmd */
if((n_read = read(sfd, newnode, sizeof(Node))) == 0)
{
if(head != NULL)
{
err_quit(sfd);
}
close(sfd);
pthread_exit(NULL);
}
switch(newnode->ack)
{
case log:
{
log_1(sfd,newnode);
break;
}
case reg:
{
reg_1(sfd,newnode);
break;
}
case sayto:
{
sayto_1(sfd, newnode);
break;
}
case sayall:
{
sayall_1(sfd, newnode);
break;
}
case dis:
{
dis_1(sfd, newnode);
break;
}
case change:
{
change_1(sfd, newnode);
break;
}
case send_file:
{
send_1(sfd, newnode);
break;
}
case stop_say:
{
stop_say_1(sfd, newnode);
break;
}
case let_say:
{
let_say_1(sfd, newnode);
break;
}
case t_man:
{
t_man_1(sfd, newnode);
break;
}
case quit:
{
quit_1(sfd, newnode);
break;
}
}
}
}
Scripts:
CC := gcc
CFLAGS := -Wall -O3
Libs = -lpthread -lsqlite3
Target := server
Source := $(wildcard src/*.c)
Objs := $(patsubst %.c,%.o,$(Source))
Modules += chat creat_table get log_reg main quit_1 read_msg sup tcp_socket
AllObjs := $(addsuffix /src/*.o,$(Modules))
/*********************************************************
- File name :send_1.c
* ******************************************************/
int send_1(int sfd, Node *newnode)
{
char buf[100];
char *sql;
char *errmsg;
int nrow;
int ncolumn;
char **azresult;
/* 接受name,检查是否在线 */
memset(buf, 0, sizeof(buf));
sprintf(buf, "select * from client_inform where name = '%s' or id = '%s';", newnode->toname, newnode->toname);
sql = buf;
if(SQLITE_OK != sqlite3_get_table(db, sql, &azresult, &nrow, &ncolumn, &errmsg))
{
perror("sqlite3_get_table send error!\n");
exit(0);
}
if(nrow == 0)
{
newnode->ack = NOT_EXIT;
write(sfd, newnode, sizeof(Node));
return 0;
}
else if(nrow == 1)
{
Online *temp = head;
while(temp != NULL)
{
if(strcmp(newnode->toname, temp->name) == 0)
{
newnode->ack = RECV_FILE;
write(temp->sfd, newnode, sizeof(Node));
return 0;
}
temp = temp->next;
}
/* 无其他用户在线 */
newnode->ack = No_online;
write(sfd, newnode, sizeof(Node));
}
return 0;
}
/*********************************************************
- File name :sup.c
* ******************************************************/
#include "../../include/net.h"
int stop_say_1(int sfd, Node *newnode)
{
Online *temp = head;
while(temp != NULL)
{
if(strcmp(newnode->name, temp->name) == 0)
{
temp->speek_flag = 0;
newnode->ack = STOP_SAY_OK;
write(sfd, newnode, sizeof(Node));
/* 通知被禁言用户已被禁言 */
newnode->ack = No_say;
write(temp->sfd, newnode, sizeof(Node));
break;
}
temp = temp->next;
}
return 0;
}
int let_say_1(int sfd, Node *newnode)
{
Online *temp = head;
while(temp != NULL)
{
if(strcmp(newnode->name, temp->name) == 0)
{
if(temp->speek_flag == 0) //该用户之前被禁言
{
temp->speek_flag = 1;
newnode->ack = LET_SAY_OK;
write(sfd, newnode, sizeof(Node));
/* 通知用户被解禁 */
newnode->ack = Ok_say;
write(temp->sfd, newnode, sizeof(Node));
return 0;
}
else if(temp->speek_flag == 1)
{
newnode->ack = NOT_STOP_SAY; //该用户没有被禁言
write(sfd, newnode, sizeof(Node));
//newnode->ack = Ok_say;
//write(temp->sfd, newnode, sizeof(Node));
return 0;
}
}
temp = temp->next;
}
return 0;
}
int t_man_1(int sfd, Node *newnode)
{
Online *temp = head;
Online *ptr;
if(strcmp(newnode->name, temp->name) == 0)
{
head = head->next;
newnode->ack = T_OK;
write(sfd, newnode, sizeof(Node));
newnode->ack = YOU_OUT;
write(temp->sfd, newnode, sizeof(Node));
temp->on_flag = 0;
ptr = temp;
temp = temp->next;
return 0;
}
while(temp != NULL)
{
if(strcmp(newnode->name, temp->name) == 0)
{
newnode->ack = T_OK;
write(sfd, newnode, sizeof(Node));
newnode->ack = YOU_OUT;
write(temp->sfd, newnode, sizeof(Node));
temp->on_flag = 0;
ptr->next = temp->next;
return 0;
}
ptr = temp;
temp = temp->next;
}
newnode->ack = No_online;
write(sfd, newnode, sizeof(Node));
return 0;
}
/*********************************************************
- File name :tcp_socket.c
* ******************************************************/
#include "../../include/net.h"
int tcp_init()
{
int sfd;
int opt = 1;
if((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket error!\n");
exit(-1);
}
struct sockaddr_in severaddr;
bzero(&severaddr, sizeof(severaddr));
severaddr.sin_family = AF_INET;
severaddr.sin_addr.s_addr = htonl(INADDR_ANY);
severaddr.sin_port = htons(8888);
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if(bind(sfd, (struct sockaddr *)&severaddr, sizeof(severaddr)) == -1)
{
perror("bind error!\n");
close(sfd);
exit(-1);
}
if(listen(sfd,1024) == -1)
{
perror("listen error!\n");
close(sfd);
exit(-1);
}
return sfd;
}
int tcp_accept(int sfd)
{
struct sockaddr_in cliaddr;
memset(&cliaddr, 0, sizeof(cliaddr));
int connfd;
unsigned int clilen = sizeof(cliaddr);
if((connfd = accept(sfd, (struct sockaddr *)&cliaddr, &clilen)) == -1)
{
perror("accept error!\n");
close(sfd);
exit(-1);
}
printf("%s %d success connect\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
return connfd;
}