即时通讯软件

客户端:

#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 = &check;//登录成功标志变量 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; }//回调函数查找