客户端:
#include <stdio.h>
#include <errno.h>#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <sqlite3.h>
#include <signal.h>
#define PORT 9999
//判断在线情况标识符,1表示在线正常,2表示被踢下线,3表示被禁言
int *adress_online;
int *adress_socketfd;
struct client_msg
{
int cmd_c; //0表示注册成功 1表示登录成功 2表示登录失败 3表示私聊信息发送成功 4表示私聊信息发送失败
int id_c;
int cmd2_c;
char name_c[20];
char psw[10];
char tak_c[100];
};
struct server_msg
{
int cmd_s;
int id_s;
char fname[20];
char tak_s[100];
};
static void * handle_client(void *arg);
void signal_handler(struct sigaction *act); //看看就好,不要尝试,会出bug;
int main(int argc, char *argv[])
{
if(2 != argc)
{
printf("Usage : %s ip\n", argv[0]);
exit(EXIT_FAILURE);
}
//建立socket***********************************
int socket_fd;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_fd)
{
perror("socket");
exit(EXIT_FAILURE);
}
adress_socketfd = &socket_fd;
//请求连接***************************************
struct hostent *host;
host = gethostbyname(argv[1]);
struct sockaddr_in clientaddr;
if(NULL == host)
{
perror("gethostbyname");
exit(EXIT_FAILURE);
}
memset(&clientaddr, 0, sizeof(struct sockaddr));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(PORT);
clientaddr.sin_addr = *((struct in_addr *)host->h_addr);
int ret;
ret = connect(socket_fd, (struct sockaddr*)(&clientaddr), sizeof(struct sockaddr));
if(-1 == ret)
{
perror("connect");
exit(EXIT_FAILURE);
}
printf("******************连接成功************************\n");
struct client_msg client1;
char snd_buf[1024];
char buffer[1024];
pthread_t cli_thread;
while(1)
{
printf("*****请输入指令*****\n");
printf("*****************************\n");
printf("** 1:注册 ****\n");
printf("** 2:登录 ****\n");
printf("** 3:退出程序 ****\n");
printf("*****************************\n");
scanf("%d", &client1.cmd_c);
switch(client1.cmd_c)
{
case 1://************注册*******************************
{
char psw_2[10];
printf(" *****************************\n");
printf(" ***** 注册 *****\n");
printf(" ***** 请输入用户名 *****\n");
scanf("%s", client1.name_c);
printf(" ***** 请输入密码 *****\n");
scanf("%s", client1.psw);
//*********确认密码***********
printf(" ***** 请再次输入密码*****\n");
scanf("%s", psw_2);
int same = 1;
same = strcmp(psw_2, client1.psw);
if(0 != same)
{
printf(" <<<<两次密码输入不同,注册失败>>>>\n");
break;
}
printf(" 正在向服务器发送请求......\n");
//**************发送信息************************
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" 发送成功,等待服务器处理......\n");
ret = read(socket_fd, buffer, 1024);
if(-1 == ret)
{
printf("read fail\n");
perror("read");
exit(EXIT_FAILURE);
}
//printf("read success\n");
struct server_msg fserver; //定义结构体变量
memset(&fserver, 0, sizeof(fserver));//清空结构体
memcpy(&fserver, buffer, sizeof(fserver));//把接收到的信息转换成结构体
if(0 != fserver.cmd_s)
{
printf(" <<<<注册失败>>>>\n");
break;
}
printf("\n");
printf(" 注册成功,您的ID是:%d\t!\n", fserver.id_s);
printf("\n");
break;
}
case 2://************登录*******************************
{
printf(" **********登录**************\n");
printf(" *** 请输入ID ****\n");
scanf("%d", &client1.id_c);
printf(" *** 请输入密码 ****\n");
scanf("%s", client1.psw);
printf(" 登录中...\n");
printf("\n");
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
//printf("发送成功,等待服务器处理......\n");
ret = read(socket_fd, buffer, 1024);
if(-1 == ret)
{
printf("read fail\n");
perror("read");
exit(EXIT_FAILURE);
}
struct server_msg fserver; //定义结构体变量
memset(&fserver, 0, sizeof(fserver));//清空结构体
memcpy(&fserver, buffer, sizeof(fserver));//把接收到的信息转换成结构体
if(1 == fserver.cmd_s)//普通用户登录
{
int online = 1;
adress_online = &online;
ret = pthread_create(&cli_thread, NULL, handle_client, (void *)socket_fd);
if(-1 == ret)
{
perror("pthread_create");
exit(EXIT_FAILURE);
}
printf(" 用户登录成功\n");
//登录成功,*******************************************************************
while(1)
{
printf("\n");
printf("***********************************************************\n");
printf(" *************请输入指令***********\n");
printf(" ****** 1:在线人数查询 ******\n");
printf(" ****** 2:私聊 *****\n");
printf(" ****** 3:群聊 ******\n");
printf(" ****** 4:注销 ******\n");
printf(" ****** 8:文件传输 ******\n");
printf("***********************************************************\n");
printf("\n");
scanf("%d", &client1.cmd2_c);
if(1 == online)
{
printf("online is %d\n", online);
}
else
{
if(2 == online)
{
printf("online is %d\n", online);
goto label1;
}
}
switch(client1.cmd2_c)//判断命令
{
case 1:
{
printf("\n");
printf("********************在线人数查询***********************\n");
//给服务器发消息
//printf("发送信息ing\n");
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" 发送请求成功,等待服务器处理......\n");
break;
}
case 2:
{
printf("\n");
if(3 != online)
{
printf("*********************私聊********************\n");
printf(" 请输入对方ID:\n");
scanf("%d", &client1.id_c);
printf(" 请输入聊天内容:\n");
scanf("%s", client1.tak_c);
//发送信息
printf(" ......\n");
//printf("1客户机命令:%d\n", client1.cmd2_c);
//memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
//printf("2客户机命令:%d\n", client1.cmd2_c);
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <私聊>请求发送成功,等待服务器处理......\n");
break;
}
else
{
printf(" 您被管理员禁言,不能发起私聊\n");
break;
}
}
case 3:
{
printf("\n");
if(3 != online)
{
printf("*********************群聊模式开启************************\n");
printf(" 请输入群聊内容:\n");
scanf("%s", client1.tak_c);
//printf("群聊内容是 :%s\n", client1.tak_c);
printf(" ......\n");
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <群聊>信息发送成功,等待服务器处理......\n");
break;
}
else
{
printf(" 您被管理员禁言,不能发起群聊\n");
break;
}
}
case 4:
{
printf("\n");
printf("*********************注销***************\n");
printf(" 发送注销请求.....\n");
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <注销>信息发送成功,等待服务器处理......\n");
goto label1;
}
case 8:
{
printf("\n");
printf("******************文件传输********************\n");
printf(" 请输入文件名:\n");
scanf("%s", client1.name_c);
printf(" 请输入发送方Id:\n");
scanf("%d", &client1.id_c);
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("<文件传输>信息发送成功\n");
FILE * fp = fopen(client1.name_c, "r");
if(NULL == fp )
{
printf(" File:\t%s Not Found\n", client1.name_c);
}
else
{
char buffer_file[1024];
memset(buffer_file, 0, 1024); //用0清空
int file_block_length = 0;
while( (file_block_length = fread(buffer_file, sizeof(char), 1024, fp)) > 0) //把fp读到buffer_file中返回值为实际长度
{
printf(" file_block_length = %d\n",file_block_length);
if(write(socket_fd, buffer_file, 1024) != -1) //send发送,失败返回值为-1
{
printf(" Send File:\t%s Failed\n", client1.name_c);
break;
}
bzero(buffer_file, 1024); //必须清空
}
fclose(fp);
printf(" 文件主体发送完成\n");
strcpy( buffer_file , "END");
printf(" client (发送) buffer is %s\n", buffer_file);
if(write(socket_fd, buffer_file, 1024) < 0)
{
printf(" Send File: Failed\n");
break;
}
printf(" 文件传输完成\n");
}
break;
}
}
}
}
else //超级用户登录
{
if(10 == fserver.cmd_s)
{
printf(" 恭喜成为管理员\n");
ret = pthread_create(&cli_thread, NULL, handle_client, (void *)socket_fd);
if(-1 == ret)
{
perror("pthread_create");
exit(EXIT_FAILURE);
}
printf(" 登录成功\n");
//登录成功,*******************************************************************
while(1)
{
printf("\n");
printf("***********************************************************\n");
printf(" *************请输入指令***********\n");
printf(" ****** 1:在线人数查询 ******\n");
printf(" ****** 2:私聊 *****\n");
printf(" ****** 3:群聊 ******\n");
printf(" ****** 4:注销 ******\n");
printf(" ****** 5:踢人 ******\n");
printf(" ****** 6:禁言 ******\n");
printf(" ****** 7:解禁 ******\n");
printf(" ****** 8:文件传输 ******\n");
printf("***********************************************************\n");
printf("\n");
scanf("%d", &client1.cmd2_c);
switch(client1.cmd2_c)//判断命令
{
case 1:
{
printf("\n");
printf("********************在线人数查询***********************\n");
//给服务器发消息
//printf("发送信息ing\n");
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" 发送请求成功,等待服务器处理......\n");
break;
}
case 2:
{
printf("\n");
printf("*********************私聊********************\n");
printf(" 请输入对方ID:\n");
scanf("%d", &client1.id_c);
printf(" 请输入聊天内容:\n");
scanf("%s", client1.tak_c);
//发送信息
printf(" ......\n");
//printf("1客户机命令:%d\n", client1.cmd2_c);
//memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
//printf("2客户机命令:%d\n", client1.cmd2_c);
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <私聊>请求发送成功,等待服务器处理......\n");
break;
}
case 3:
{
printf("\n");
printf("*********************群聊模式开启************************\n");
printf(" 请输入群聊内容:\n");
scanf("%s", client1.tak_c);
//printf("群聊内容是 :%s\n", client1.tak_c);
printf(" ......\n");
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <群聊>信息发送成功,等待服务器处理......\n");
break;
}
case 4:
{
printf("\n");
printf("*********************注销***************\n");
printf(" 发送注销请求.....\n");
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <注销>信息发送成功,等待服务器处理......\n");
goto label1;
}
case 5:
{
printf("*********************踢人****************\n");
printf(" 请输入被踢者的ID\n");
scanf("%d", &client1.id_c);
printf(" ......\n");
//printf("1客户机命令:%d\n", client1.cmd2_c);
//memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
//printf("2客户机命令:%d\n", client1.cmd2_c);
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <踢人>请求发送成功,等待服务器处理......\n");
break;
}
case 6:
{
printf("*********************禁言****************\n");
printf(" 请输入被禁言者ID\n");
scanf("%d", &client1.id_c);
printf(" ......\n");
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
//printf("2客户机命令:%d\n", client1.cmd2_c);
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <禁言>请求发送成功,等待服务器处理......\n");
break;
}
case 7:
{
printf("*********************解禁***************\n");
printf(" 请输入要解禁的人的ID\n");
scanf("%d", &client1.id_c);
printf(" ......\n");
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
//printf("2客户机命令:%d\n", client1.cmd2_c);
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" <解禁>请求发送成功,等待服务器处理......\n");
break;
}
case 8:
{
printf("\n");
printf("******************文件传输********************\n");
printf(" 请输入要发送的文件名:\n");
scanf("%s", client1.name_c);
// printf(" 请输入接收的文件名:\n");
// scanf("%s", client1.name_r);
printf(" 请输入发送方Id:\n");
scanf("%d", &client1.id_c);
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("<文件传输>信息发送成功\n");
FILE * fp = fopen(client1.name_c, "r");
if(NULL == fp )
{
printf(" File:\t%s Not Found\n", client1.name_c);
}
else
{
char buffer_file[1024];
memset(buffer_file, 0, 1024); //用0清空
int file_block_length = 0;
while( (file_block_length = fread(buffer_file, sizeof(char), 1024, fp)) > 0) //把fp读到buffer_file中返回值为实际长度
{
printf(" file_block_length = %d\n",file_block_length);
if(write(socket_fd, buffer_file, 1024) != -1) //send发送,失败返回值为-1
{
printf(" Send File:\t%s Failed\n", client1.name_c);
break;
}
memset(buffer_file, 0,1024); //必须清空
}
fclose(fp);
printf(" 文件主体发送完成\n");
memset(buffer_file, 0,1024);
strcpy( buffer_file , "END");
printf(" client (发送) buffer is %s\n", buffer_file);
if(write(socket_fd, buffer_file, 1024) == -1)
{
printf(" Send File: Failed\n");
break;
}
printf(" 文件传输完成\n");
}
break;
}
}
}
}
}
printf("登录失败\n");
break;
}
case 3://************退出程序*******************************
{
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("用户退出\n");
goto outprogram;
}
}
label1:
printf("waiting*******************************************\n");
}
outprogram:
close(socket_fd);
return 0;
}
static void * handle_client(void *arg)
{
int ret;
int socket_fd = (int)arg;
char buffer[1024];
while(1)
{
ret = read(socket_fd, buffer, 1024);
if(-1 == ret)
{
perror("read");
exit(EXIT_FAILURE);
}
struct server_msg fserver; //定义结构体变量
memset(&fserver, 0, sizeof(fserver));//清空结构体
memcpy(&fserver, buffer, sizeof(fserver));//把接收到的信息转换成结构体
//printf("fserver.cmd_s is %d\n", fserver.cmd_s);
switch(fserver.cmd_s)
{
case 9:
{
printf("在线人数为 %d\n", fserver.id_s);
break;
}
case 3:
{
printf("私聊信息发送成功\n");
break;
}
case 4:
{
printf("私聊信息发送失败\n");
break;
}
case 5:
{
printf("%d发来私聊信息%s\n", fserver.id_s, fserver.tak_s);
break;
}
case 6:
{
printf("%d\t发来群发消息%s\n", fserver.id_s, fserver.tak_s);
break;
}
case 7:
{
printf("群聊发送成功\n");
break;
}
case 8:
{
printf("注销成功\n");
goto label2;
}
case 10:
{
printf("管理员登录成功\n");
break;
}
case 11:
{
printf("您被管理员踢出本聊天室\n");
struct client_msg client1;
char snd_buf[1024];
client1.cmd2_c = 4;
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(被踢)信息发送成功,等待服务器处理......\n");
printf("输入任意数字退出界面\n");
*adress_online = 2;
break;
}
case 12:
{
printf("踢人操作完成\n");
break;
}
case 13:
{
printf("您被管理员禁言\n");
*adress_online = 3;
break;
}
case 14:
{
printf("禁言成功\n");
break;
}
case 15:
{
printf("您被管理员解除禁言\n");
*adress_online = 1;
break;
}
case 16:
{
printf("解除禁言成功\n");
break;
}
case 17:
{
char buffer_file[1024];
printf("%d\t发来文件%s, 请注意查收\n", fserver.id_s, fserver.fname);
FILE * fp = fopen("222.txt","w+");
if(NULL == fp )
{
printf("File:\t%s Can Not Open To Write\n", fserver.fname);
exit(1);
}
//从服务器接收数据到buffer中
memset(buffer_file, 0, 1024);
int length = 0;
while(1)
{
length = read(socket_fd, buffer_file, 1024); //收到的字符串长度
printf("length = %d\n",length);
if(length < 0)
{
printf("Recieve Data From Server %s Failed!\n", fserver.fname);
break;
}
printf("client(接收) : buffer_file is %s\n", buffer_file);
if(0 == strcmp(buffer_file, "END"))
{
printf("文件接收完成\n");
break;
}
int write_length = fwrite(buffer_file, sizeof(char), length, fp);
printf("write_length = %d\n", write_length);
if (write_length < length)
{
printf("File:\t%s Write Failed\n", fserver.fname);
break;
}
memset(buffer_file, 0, 1024);
}
fclose(fp);
break;
}
case 18:
{
printf("文件传输完成\n");
break;
}
}
}
label2:
printf("waiting********************************\n");
return;
}
void signal_handler(struct sigaction *act)
{
int socket_fd = *adress_socketfd;
struct client_msg client1;
client1.cmd_c = 99;
client1.cmd2_c = 99;
char snd_buf[1024];
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &client1, sizeof(client1)); //结构体转换成字符串
int ret;
ret = write(socket_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
exit(0);
}
服务端:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <pthread.h>
#include <sqlite3.h>
//定义端口
#define PORT 9999
//登录成功标志变量地址
int *adress;
//客户机结构体
struct client_msg
{
int cmd_c; //功能选项 1.注册 2.登录。3.退出
int id_c;
int cmd2_c; //功能选项 1.客户机查看在线人数。2.私聊。3.群聊。4.注销。5.超级用户踢人。6.禁言。7.解禁。8.文件传输。99.客户机强退。
char name_c[20];
char psw[10];
char tak_c[100];
};
//服务器结构体
struct server_msg
{
int cmd_s; //0表示注册成功 1表示登录成功 2表示登录失败 3表示私聊信息发送成功 4表示私聊信息发送失败
int id_s;
char fname[20];
char tak_s[100];
};
//链表结构体
typedef struct Node
{
int id_l;
int fd_l;
struct Node *next;
}linkedlist;
linkedlist *list;
//链表函数
linkedlist *createlinkedlist();
int getcount(linkedlist *list);
//void insert1(linkedlist *list, int id, int fd);
linkedlist *insert2(linkedlist *list, int id, int fd);
int queryfd(linkedlist *list, int id);
int queryid(linkedlist *list, int fd);
void print(linkedlist *list);
linkedlist *dellinkedlist(linkedlist *list, int fd);
//线程处理函数
static void * handle_client(void * arg);
//回调函数
int select_callback(void *date, int column_count,char* columnValue[],char* columnName[]);
int main()
{
//用来创建socket
int socket_fd;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_fd)
{
perror("socket");
exit(EXIT_FAILURE);
}
printf("socket success\n");
//用来绑定
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(struct sockaddr));
myaddr.sin_family = AF_INET;//设置协议
myaddr.sin_port = htons(PORT);//端口号
myaddr.sin_addr.s_addr = INADDR_ANY;//任意ip都可以通信
int ret;
ret = bind(socket_fd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr));
if(-1 == ret)
{
perror("bind");
exit(EXIT_FAILURE);
}
printf("bind success\n");
//监听
ret = listen(socket_fd, 6);
if(-1 == ret)
{
perror("listen");
exit(EXIT_FAILURE);
}
printf("listen success\n");
struct sockaddr_in clientaddr;
pthread_t cli_thread;
//建立数据库
int sqlret;
sqlite3 *db;
char *ErrMsg;
sqlret = sqlite3_open("./chatroom.db", &db);//打开数据库
if(sqlret != SQLITE_OK)
{
printf("error : open sqlite\n");
}
printf("建立数据库成功\n");
char *create_str = "create table people (id INTEGER primary key, name TEXT, psw TEXT);";
sqlret = sqlite3_exec(db, create_str, 0, 0, &ErrMsg);
if(sqlret != SQLITE_OK)
{
printf("error : create %s\n", sqlite3_errmsg(db));
}
printf("建立表成功\n");
//关闭数据库
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
printf("error : close\n");
}
char snd_buf[1024];
//创建链表
list = createlinkedlist();
while(1)
{
int size = sizeof(struct sockaddr_in);
//此处发生第一次阻塞,满足条件:有新的客户端接入
int new_fd;
new_fd = accept(socket_fd, (struct sockaddr*)&clientaddr, &size);
if(-1 == new_fd)
{
perror("accept");
}
printf("accept success\n");
//线程处理新接入的客户机
ret = pthread_create(&cli_thread, NULL, handle_client, (void *)new_fd);
if(-1 == ret)
{
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
return 0;
}
static void * handle_client(void *arg)
{
int new_fd = (int)arg;
char buffer[1024];
char snd_buf[1024];
int ret;
static int num = 520;//用作id
while(1)
{
//接收信息
printf("reading...\n");
ret = read(new_fd, buffer, 1024);
if(-1 == ret)
{
printf("read fail\n");
perror("read");
exit(EXIT_FAILURE);
}
printf("read success\n");
//解析信息
struct client_msg fclient; //定义结构体变量
memset(&fclient, 0, sizeof(fclient));//清空结构体
memcpy(&fclient, buffer, sizeof(fclient));//把接收到的信息转换成结构体
//printf("%d\t%s\t%s\t%s\n", fclient.cmd_c, fclient.name_c, fclient.psw, fclient.tak_c);
struct server_msg server1;
server1.cmd_s = -1;
switch(fclient.cmd_c)
{
case 1:
{
printf("有新的客户请求注册\n");
//*********插入注册信息****************
int sqlret;
sqlite3 *db;
sqlret = sqlite3_open("./chatroom.db", &db);
if(sqlret != SQLITE_OK)
{
printf("error : open sqlite\n");
}
char *insert_str = "insert into people (id, name, psw) values (%d, '%s', '%s');";
char *ErrMsg;
char str[1024];
//插入注册信息到people表
sprintf(str, insert_str, num, fclient.name_c, fclient.psw);
ret = sqlite3_exec(db, str, 0, 0, &ErrMsg);
if(ret != SQLITE_OK)
{
printf("error : insert %s\n", sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
printf("error : close\n");
}
server1.cmd_s = 0;
server1.id_s = num;
num++;
//***********发送服务器结构体*********
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("发送成功,等待下一指令......\n");
break;
}
case 2:
{
printf("有新的客户端请求登录\n");
//printf("%d\t%s\t%s\t%d\n", fclient.cmd_c, fclient.name_c, fclient.psw, fclient.id_c);
//回调函数查找
int ret;
sqlite3 *db;
char *ErrMsg;
char str[1024];
//打开数据库
ret = sqlite3_open("./chatroom.db", &db);
if(ret != SQLITE_OK)
{
printf("error : open\n");
}
//查找表内数据
int check = -1;
adress = ✓//登录成功标志变量
printf("*********查询信息********\n");
char *select_str = "select * from people where id = %d and psw = '%s';";
sprintf(str, select_str, fclient.id_c, fclient.psw);
printf("开始查找\n");
ret = sqlite3_exec(db, str, select_callback, 0, &ErrMsg);
if(ret != SQLITE_OK)
{
printf("error : select %s\n", sqlite3_errmsg(db));
break;
}
printf("check = %d\n", check);
//关闭数据库
ret = sqlite3_close(db);
if(ret != SQLITE_OK)
{
printf("error : close\n");
}
if(check == 1)//登录成功
{
//server1.cmd_s = 1;
if(520 == fclient.id_c)
{
server1.cmd_s = 10;
}
else
{
server1.cmd_s = 1;
}
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("登录成功,发送反馈成功,等待下一指令......\n");
//插入信息到链表
list = insert2(list, fclient.id_c, new_fd);
printf("现在打印链表\n");
print(list);
printf("在线人数为:%d\n", getcount(list));
//reading...
while(1)
{
printf("现在等待客户端命令\n");
//**************读取信息*******************************************
memset(buffer, 0, 1024);
ret = read(new_fd, buffer, 1024);
if(-1 == ret)
{
printf("read fail\n");
perror("read");
exit(EXIT_FAILURE);
}
printf("read success\n");
//解析信息
struct client_msg fclient; //定义结构体变量
memset(&fclient, 0, sizeof(fclient));//清空结构体
memcpy(&fclient, buffer, sizeof(fclient));//把接收到的信息转换成结构体
//******************读取完成****************************************
printf("客户端命令为 :%d\n", fclient.cmd2_c);
switch(fclient.cmd2_c)
{
case 1://客户机请求查看在线人数
{
printf("客户机请求查看在线人数\n");
server1.cmd_s = 9;
print(list);
server1.id_s = getcount(list);
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("发送反馈成功,等待下一指令......\n");
break;
}
case 2://私聊
{
printf("私聊ID:%d\t私聊内容:%s\n", fclient.id_c, fclient.tak_c);
int send_fd = queryfd(list, fclient.id_c);
printf("1send_fd is %d\n", send_fd);
if(0 != send_fd)
{
printf("2send_fd is %d\n", send_fd);
strcpy(server1.tak_s, fclient.tak_c);//私聊信息存到服务器结构体
printf("本身id :%d\n", queryid(list, new_fd));
server1.id_s = queryid(list, new_fd);
server1.cmd_s = 5;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(send_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(私聊信息)发送成功\n");
server1.cmd_s = 3;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(私聊反馈)发送成功\n");
}
else
{
printf("(私聊信息)发送失败\n");
server1.cmd_s = 4;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(私聊反馈)发送成功\n");
}
break;
}
case 3://群聊
{
printf("客户机请求群聊\n");
server1.id_s = queryid(list, new_fd);
printf("发起人%d\t群聊内容:%s\n", server1.id_s, fclient.tak_c);
int i;
linkedlist *h = list;
for(i = 0; i<getcount(list); i++)
{
if(h -> fd_l != new_fd)
{
strcpy(server1.tak_s, fclient.tak_c);//私聊信息存到服务器结构体
//printf("本身id :%d\n", queryid(list, new_fd));
server1.cmd_s = 6;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(h -> fd_l, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf(" (私聊信息)发送成功\n");
}
h = h -> next;
}
server1.cmd_s = 7;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(私聊反馈)发送成功\n");
break;
}
case 4://注销
{
printf("用户请求注销下线\n");
list = dellinkedlist(list, new_fd);
print(list);
server1.cmd_s = 8;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(注销反馈)发送成功\n");
goto label1;
}
case 5://踢人
{
printf("超级用户请求踢人,被踢者ID为%d\n", fclient.id_c);
int ti_fd = queryfd(list, fclient.id_c);
//list = dellinkedlist(list, ti_fd);
//print(list);
server1.cmd_s = 11;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(ti_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(踢人指令)发送成功\n");
server1.cmd_s = 12;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(踢人反馈)发送成功\n");
break;
}
case 6://禁言
{
printf("超级用户请求禁言,被禁言者ID为%d\n");
int jin_fd = queryfd(list, fclient.id_c);
server1.cmd_s = 13;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(jin_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(禁言指令)发送成功\n");
server1.cmd_s = 14;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(禁言反馈)发送成功\n");
break;
}
case 7://解禁
{
printf("超级用户请求解除禁言,被解除者ID为%d\n");
int jiejin_fd = queryfd(list, fclient.id_c);
server1.cmd_s = 15;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(jiejin_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(解禁指令)发送成功\n");
server1.cmd_s = 16;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(解禁反馈)发送成功\n");
break;
}
case 8://文件传输
{
printf("客户机请求发送文件******************\n");
printf("发送给%d\t文件名:%s\n", fclient.id_c, fclient.name_c);
int id_sdf = queryid(list, new_fd);
int fd_rsvf = queryfd(list, fclient.id_c);
server1.cmd_s = 17;
server1.id_s = id_sdf;
strcpy(server1.fname, fclient.name_c);
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(fd_rsvf, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(文件传输指令)发送成功\n");
转发
//while(1)
printf("文件发送ing\n");
char buffer_file[1024] = {0};
while(read(new_fd, buffer_file, 1024) != -1) //失败返回-1
{
printf("server : buffer_file is %s\n", buffer_file);
if(write(fd_rsvf, buffer_file, 1024) == -1) //失败返回-1
{
perror("send");
exit(-1);
}
if(0 == strcmp(buffer_file, "END"))
{
printf("文件主体传输完成\n");
break;
}
memset(buffer_file, 0, 1024);//清空缓存
}
perror("recv");
//exit(-1);
server1.cmd_s = 18;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("(文件传输反馈)发送成功\n");
break;
}
case 99://客户机强行退出
{
printf("客户机强行退出\n");
list = dellinkedlist(list, new_fd);
print(list);
goto label1;
}
}
}
}
else//登录失败
{
server1.cmd_s = 2;
memset(snd_buf, 0, 1024);//清空发送缓存
memcpy(snd_buf, &server1, sizeof(server1)); //结构体转换成字符串
ret = write(new_fd, snd_buf, 1024);//发送信息
if(-1 == ret)
{
perror("write");
exit(EXIT_FAILURE);
}
printf("登录失败,发送反馈成功,等待下一指令......\n");
break;
}
break;
}
case 3:
{
printf("客户机退出程序\n");
goto clientout;
}
case 99:
{
printf("客户机强行退出\n");
goto clientout;
}
}
label1:
printf("**************\n");
}
clientout:
close(new_fd);
}
linkedlist *createlinkedlist()
{
linkedlist *h;
h = NULL;
return h;
}
linkedlist *dellinkedlist(linkedlist *list, int fd)
{
linkedlist *p = list -> next;
linkedlist *h = list;
if(list -> fd_l == fd)
{
free(h);
return list -> next;
}
else
{
while(p -> fd_l != fd)
{
p = p -> next;
h = h -> next;
}
h -> next = p -> next;
free(p);
return list;
}
}
linkedlist *insert2(linkedlist *list, int id, int fd)
{
linkedlist *head, *p;
head = list;
p = (linkedlist *)malloc(sizeof(linkedlist));
if(head == NULL)
{
head = p;
p -> next = NULL;
}
else
{
p -> next = head;
head = p;
}
p -> id_l = id;
p -> fd_l = fd;
return head;
}
int getcount(linkedlist *list)
{
linkedlist *h = list;
int count = 0;
while(h != NULL)
{
count++;
h = h -> next;
}
return count;
}
int queryid(linkedlist *list, int fd)
{
linkedlist *p, *h;
h = list;
while(h != NULL)
{
if(fd == h -> fd_l)
{
return h -> id_l;
}
h = h -> next;
}
}
int queryfd(linkedlist *list, int id)
{
linkedlist *h = list;
while(h != NULL)
{
if(id == h -> id_l)
{
return h -> fd_l;
}
h = h -> next;
}
return 0;
}
void print(linkedlist *list)
{
linkedlist *h = list;
while(h != NULL)
{
printf("list id is %d\tfd is %d\n",h ->id_l, h -> fd_l);
h = h -> next;
}
printf("\n");
}
int select_callback(void *date, int column_count,char* columnValue[],char* columnName[])//回调函数查找
{
if(column_count != 0)
{
*adress = 1;
}
else
{
*adress = 2;
}
return 0;
}//回调函数查找