即时通讯软件

客户端:

#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;
}//回调函数查找







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值