这个聊天室完成了一些基础功能私聊、群聊、文件传送等基础功能,可以添加表情符号等其他功能。
头文件中的名称的定义可以换成枚举形式,会更加方便一点,我脑抽了就不改了。有空再完善代码规范和功能。
myhead.h
#ifndef _MYHEAD_H_
#define _MYHEAD_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <sqlite3.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFSIZE 50
#define MYPORT 6656
#define MYADDR "192.168.1.200"
/**功能选择**/
#define REG 1
#define LOGIN 2
#define PRIVATE_CHAT 3
#define GROUP_CHAT 4
#define VIEW_FRIENDS 5
#define CORRECT_PIN_NUMBER 6
#define ADMINI_PRIVILEGE 7
#define SEND_OFFLINE_MSG 8
#define SEND_FILE 9
#define SIGN 10
#define OFF_LINE 11
#define VIEW_USER_MSG 26
#define BECOME_VIP 39 //成为VIP
/**登陆注册**/
#define REG_SUCCESS 12
#define REG_FAIL 13
#define LOGIN_SUCCESS 14
#define LOGIN_FAIL 15
#define LOGIN_EXIT 16
/**创建链表**/
#define CREATE_NODE 17
/************/
#define PRIVATE_SUCCESS 18
#define PRIVATE_FAIL 19
#define GROUP_SUCCESS 20
#define VIEW_FRIENDS_SUCCESS 21
#define CORRECT_SUCCESS 22
#define CORRECT_FAIL 23
#define CORRECT_OLD 24 //用户原密码输入错误
#define OFF_LINE_SUCCESS 27
#define OFF_LINE_FAIL 28
/**权限**/
#define BAN 29 //禁言
#define REMOVE 30 //解禁
#define KICK 31 //踢人
#define BAN_USER 32 //返回给被禁言的用户
#define REMOVE_USER 33 //返回给被解禁的用户
#define KICK_FAIL 34
#define BEEN_KICK 35
#define NO_POWER 36 //没有vip权限
#define SIGN_SUCCESS 37
#define SEND_SUCCESS 38 //发送离线消息成功
#define VIP_SUCCESS 42
//#define BECOME_VIP 39 //成为VIP
#define SHOW_INFO 43
/**文件**/
#define FILE_SUCCESS 40
#define FILE_FAIL 41
typedef struct users //用户信息:链表
{
//struct regist *user;
char username[20]; //用户名
int clientfd;
int power; //1:禁言,0:未禁言
struct users *next;
}user;
typedef struct regist //注册
{
int flag; //注册登录标志符
int vip; //会员用户 为1时具有会员权限,为0没有
char username[20]; //用户名
char password[20]; //密码
char new_passwd1[20]; //新密码
char new_passwd2[20]; //新密码验证
char file[1024]; //文件
char filename[20]; //文件名
char sign[50]; //个性签名
// int friend_num; //好友数
// int group_num; //群组数
char offline_msg[500]; //离线消息
int action; //通过action表明是什么命令;
char fromname[20];
char toname[20];
char time[20]; //时间
char msg[500]; //消息内容
}client;
char my_getch()
{
char temp = 0;
temp = getchar();
}
#endif
server.c
#include "myhead.h"//server
void *read_msg_server(void *argc);
void register_client(int clientfd);
void login_client(int clientfd);
void private_chat(int clientfd);
sqlite3 *db = NULL;
char *errmsg = NULL;
char **result = NULL;
char sql[1024] = {0};
struct users *head = NULL; //创建用户信息的头结点
user userbuff;
client clientrecv;
int main()
{
int socketfd = 0;
int clientfd = 0;
int ret = 0;
struct sockaddr_in server_addr = {0};
struct sockaddr_in client_addr = {0};
socklen_t len = sizeof(struct sockaddr);
pthread_t th;
char recvbuff[20] = {0};
int recvcnt = 0;
char sendbuff[20] = {0};
int sendcnt = 0;
head = (struct users*)malloc(sizeof(struct users));
if(head == NULL)
{
printf("malloc error\n");
}
//head->next = NULL;
ret = sqlite3_open("chat.db",&db); //建数据库
if(ret != SQLITE_OK)
{
printf("数据库打开失败!");
}
sqlite3_exec(db,"create table account(username text primary key,password text,vip INTEGER,sign text,offline_msg text);",NULL,NULL,&errmsg); //建注册信息表
socketfd = socket(AF_INET,SOCK_STREAM,0); //1.调用socket创建套接字
if(socketfd == -1)
{
perror("socket");
return -1;
}
printf("socket success...\n");
bzero(&server_addr,sizeof(server_addr)); //2.绑定:==》地址族,端口号,IP地址;下面就是赋值操作!
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MYPORT);
server_addr.sin_addr.s_addr = inet_addr(MYADDR);
ret = bind(socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
if(ret == -1)
{
perror("bind");
return -1;
}
printf("bind success...\n");
ret = listen(socketfd,10);
if(ret == -1)
{
perror("listen");
return -1;
}
printf("listen success...\n");
while(1)
{
clientfd = accept(socketfd,(struct sockaddr *)&client_addr,&len);
if(clientfd == -1)
{
perror("accept");
return -1;
}
printf("accept success... ");
if(pthread_create(&th,NULL,read_msg_server,&clientfd) == -1)
{
perror("pthread_create");
return -1;
}
pthread_detach(th);
}
// close(socketfd);
sqlite3_free_table(result);
slqite3_close(db);
return 0;
}
void *read_msg_server(void *argc)
{
struct users *p = head;
int clientfd = *((int *)argc);
printf("read_msg_server:clientfd = %d\n",clientfd);
int readcnt = 0;
int writecnt = 0;
while(1)
{
int login_flag = 0;
memset(&clientrecv,0,sizeof(client));
readcnt = read(clientfd,&clientrecv,sizeof(client));
if(readcnt == -1)
{
perror("read_msg_client:read");
return 0;
}
switch(clientrecv.action)
{
case 1: //注册
{
register_client(clientfd);
break;
}
case 2: //登录
{
//login_client(clientfd);
int i = 0;
int j = 0;
int nrow = 0; //行
int ncolumn = 0; //列
int flag = 0;
int ret = 0;
int readcnt =0;
ret = sqlite3_get_table(db,"select * from account",&result,&nrow,&ncolumn,&errmsg);
for(i = 1; i <= nrow; i++)
{
for(j = 0; j < ncolumn; j++)
{
if(strcmp(clientrecv.username,result[i*ncolumn]) == 0 && strcmp(clientrecv.password,result[i*ncolumn+ 1]) == 0)
{
flag = 1;
//strcpy(buff,clientrecv.username);
}
}
}
p = head;
while(p->next != NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.username) == 0)
{
clientrecv.flag = LOGIN_EXIT; //该用户已登录
write(clientfd,&clientrecv,sizeof(client));
}
}
if(flag == 0) //登录失败
{
clientrecv.flag = LOGIN_FAIL;
write(clientfd,&clientrecv,sizeof(client));
}
else if(flag == 1) //登录成功
{
clientrecv.flag = LOGIN_SUCCESS;
write(clientfd,&clientrecv,sizeof(client));
struct users *new = (struct users *)malloc(sizeof(struct users));
strcpy(new->username,clientrecv.username);
new->clientfd = clientfd;
/*************************权限状态需要从数据库中读取**********************************/
new->power = 0; //未禁言状态
if(new == NULL)
{
printf("malloc error!\n");
//return NULL;
}
/* p = head;
while(p->next != NULL) //p不是尾结点
{
p = p->next;
}
*/p->next = new;
new->next = NULL;
//bzero(p,sizeof(struct users));
}
break;
}
case 3: //私聊
{
//private_chat(clientfd);
p = head;
int temp = 0;
while(p->next !=NULL)
{
p = p->next;
if(strcmp(p->username,clientrecv.toname) == 0) //存在该好友
{
temp = 1;
//clientfd = p->clientfd;
clientrecv.flag = PRIVATE_SUCCESS;
//printf("m\n");
printf("testing!!!\n");
printf("%s(%d)send to%s(%d)",clientrecv.fromname,clientfd,clientrecv.toname,p->clientfd);
write(p->clientfd,&clientrecv,sizeof(client)); //发送给好友
break;
}
}
if(temp == 0)
{
clientrecv.flag = PRIVATE_FAIL; //查无此人,回复给用户
write(clientfd,&clientrecv,sizeof(client));