主要实现的功能:
普通成员:注册,登录,私聊,群聊,保存聊天记录,改密码,下线,注销账号,
查询在线人员名单,查询离线人员名单,查询在线人员人数,
查询离线人员人数等
管理员:踢人,禁言,解禁等
服务器部分
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include<time.h>
#include<fcntl.h>
#include<sys/stat.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include <sqlite3.h>
#define portnumber 3333
sqlite3 *db;/*定义了一个数据库变量*/
sqlite3 *db1;
int fd;
struct all/*注册的时候不用有new_fd*/
{
char name[100];
char passwd[100];
struct all *next;
};
/*用来放置所有注册的人*/
struct online
{
char name[100];
char passwd[100];
int fd;
struct online *next;
};
/*用来放置所有上线的人*/
struct all *ahead=NULL;
struct online *ohead=NULL;
struct message
{
char name[100];
char passwd[100];
char to_name[100];
char to_msg[100];
int admin;
int chat;
int length;
int action;
};
void num_to_str(int num,char *str)
{
int i = 0;
int count;
char ch;
while(num != 0)
{
str[i++] = num % 10 + '0';
num = num / 10;
}
str[i] = '\0';
count = i;
for(i = 0;i < count/2;i++)
{
ch = str[i];
str[i] = str[count-1-i];
str[count-1-i] = ch;
}
}
void get_time(char *ptime)
{
time_t now;
struct tm *timenow;
char str[6][10];
time(&now);
timenow = localtime(&now);
num_to_str(timenow->tm_year+1900,str[0]);
num_to_str(timenow->tm_mon+1,str[1]);
num_to_str(timenow->tm_mday,str[2]);
num_to_str(timenow->tm_hour,str[3]);
num_to_str(timenow->tm_min,str[4]);
num_to_str(timenow->tm_sec,str[5]);
sprintf(ptime,"%s/%s/%s/%s:%s:%s",str[0],str[1],str[2],str[3],str[4],str[5]);
}
void create_table(sqlite3 *db)/*数据库里面创建了一个表*/
{
char *sql = "create table if not exists mytable (name text primary key, passwd text)";
char *errmsg;
int ret;
ret = sqlite3_exec(db/*数据库*/, sql/*操作内容*/, NULL, NULL, &errmsg/*错误原因*/);/*进行这样的一个操作*/
if (ret != SQLITE_OK)
{
printf("create table error:%s\n", errmsg);
exit (-1);
}
}
void create_tablec(sqlite3 *db)/*数据库里面创建了一个表*/
{
char *sql = "create table if not exists chatrecords (name text, sendtime text,to_name text,chat text)";
char *errmsg;
int ret;
ret = sqlite3_exec(db/*数据库*/, sql/*操作内容*/, NULL, NULL, &errmsg/*错误原因*/);/*进行这样的一个操作*/
if (ret != SQLITE_OK)
{
printf("create table error:%s\n", errmsg);
exit (-1);
}
}
void insert_record(struct message *msg)/*将注册的新成员放入数据库中*/
{
sqlite3_open("mydatabase.db",&db);
char sql[100];
char *errmsg;
int ret;
sprintf(sql,"insert into mytable (name, passwd) values ('%s','%s' );", msg->name, msg->passwd);/*把中间这一串字符放入到sql中*/
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);/*执行将之放入数据库的操作*/
if(ret != SQLITE_OK)
{
printf("insert record error :%s\n", errmsg);
return;
}
sqlite3_close(db);
return;
}
void update_record(struct message *msg)/*将要更改密码的成员的老密码更新为新密码放入数据库中*/
{
sqlite3_open("mydatabase.db",&db);
char sql[100];
char *errmsg;
int ret;
sprintf(sql,"update mytable set passwd = '%s' where name = '%s';",msg->to_msg, msg->name);/*将msg->to_msg中存放的新密码替换掉原本的密码*/
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);/*执行上面的语句*/
if(ret != SQLITE_OK)
{
printf("update record error :%s\n", errmsg);
return;
}
sqlite3_close(db);
return;
}
#if 0
void insert_crecord(struct message * msg,char *sendtime)/*表里面放入聊天记录*/
{
sqlite3_open("chatrecord.db",&db1);
char sql[100];
char *errmsg;
int ret;
sprintf(sql,"insert into chatrecords (name,sendtime,to_name,chat) values ('%s','%s','%s','%s' );", msg->name,sendtime, msg->to_name,msg->to_msg);/*把发送消息着的名字以及消息的内容放入数据库中*/
ret = sqlite3_exec(db1, sql, NULL, NULL, &errmsg);/*执行将之放入数据库的操作*/
if(ret != SQLITE_OK)
{
printf("insert record error :%s\n", errmsg);
return;
}
sqlite3_close(db1);
return;
}
#endif
void inquire_nocb(sqlite3 *db)/*用于程序一开始时把数据库里面存放的注册人员的名单复制到所有成员链表中*/
{
int nrow, ncolumn;
char **azresult;
char *errmsg;
int ret;
int i;
char *sql = "select * from mytable";
ret = sqlite3_get_table(db,sql, &azresult, &nrow, &ncolumn, &errmsg);
if(ret != SQLITE_OK)
{
printf("get table error:%s",errmsg);
exit(-1);
}
printf("nrow = %d, column = %d\n", nrow, ncolumn);
for(i = ncolumn; i < (nrow + 1)*ncolumn; i+=2)
{
printf("--------------------------\n");
struct all *N=(struct all *)malloc(sizeof(struct all));
strcpy(N->name,azresult[i]);
strcpy(N->passwd,azresult[i+1]);
insert_anode(N);
}
sqlite3_free_table(azresult);
}
int insert_anode(struct all *newnode)/*头节点放数据,用来存放所有注册人员的链表*/
{
if(ahead == NULL)
{
newnode->next = NULL;
ahead = newnode;
return 0;
}
struct all *temp = ahead;
while(temp->next != NULL)
{
temp = temp->next;
}
temp->next = newnode;
newnode->next = NULL;
return 0;
}
int over_anode()/*遍历所有注册人员的链表*/
{
struct all *p=ahead;
if(p == NULL)
{
printf("have no people in lianbiao \n");
return 0;
}
//struct all *temp = ahead;
while(p!= NULL)
{
printf("%s\n",p->name);
printf("%s\n",p->passwd);
p = p->next;
}
return 0;
}
int length_all()/*遍历所有注册人员的链表*/
{
struct all *p=ahead;
int count=0;
if(p == NULL)
{
return 0;
}
while(p!= NULL)
{
count++;
p = p->next;
}
return count;
}
int length_online()/*遍历所有注册人员的链表*/
{
struct online *p=ohead;
int count=0;
if(p == NULL)
{
return 0;
}
while(p!= NULL)
{
count++;
p = p->next;
}
return count;
}
int insert_onode(struct online *newnode)/*头节点放数据,在使用登录功能时调用用来存放在线人员的信息*/
{
if(ohead == NULL)
{
newnode->next = NULL;
ohead = newnode;
return 0;
}
struct online *temp = ohead;
while(temp->next != NULL)/*遍历到尾节点*/
{
temp = temp->next;
}
temp->next = newnode;/*插入新的节点*/
newnode->next = NULL;
return 0;
}
struct all * find_anode(char *name)/*用来登录的时候检查该帐户是否已经注册*/
{
if(ahead == NULL)
{
printf("---------------------------------------\n");
return NULL;
}
struct all *temp = ahead;
while(temp != NULL)
{
if(strcmp(temp->name,name) == 0)
{
printf("find success.\n");
return temp;
}
temp = temp->next;
}
return NULL;
}
struct online * find_onode(char *name)/*在在线链表中查找成员*/
{
if(ohead == NULL)
{
return NULL;
}
struct online *temp = ohead;
while(temp != NULL)
{
if(strcmp(temp->name,name) == 0)
{
// printf("find online success.\n");
return temp;
}
temp = temp->next;
}
return NULL;
}
void delete_online(char * name )/*删除在线节点*/
{
struct online* p1,*p2;
if(strcmp(ohead->name,name))
{
p1=ohead;
ohead=ohead->next;
free(p1);
}
else
{
p1=ohead;
while(p1->next!=NULL)
{
p2=p1;
p1=p1->next;
if(strcmp(p1->name,name)==0)
{
p2->next=p1->next;
free(p1);
break;
}
}
}
return;
}
void delete_all(char * name )/*删除在线节点*/
{
struct all *p;
struct all *q;
p=ahead;/*因为头节点是全局变量*/
q=p->next;/*第二个节点*/
if(strcmp(p->name,name)==0)/*如果要下线的是头节点*/
{
q=p;
p=p->next;/*头指针指向空*/
free(q);
printf("zhuxiao success\n");
}
while(q!=NULL)/*不是头节点的情况*/
{
if(strcmp(q->name,name)==0)
{
p->next=q->next;
free(q);
q=p->next;
printf("zhuxiao success11\n");
break;
}
p=p->next;
q=p->next;
}
}
void delete_record(char *name)/*从数据库里删除内容*/
{
char sql[100];
char *errmsg;
int ret;
{
sprintf(sql,"delete from mytable where name = ('%s');", name);/*把名字为某某的数据删掉*/
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);/*执行将之放入数据库的操作*/
if(ret != SQLITE_OK)
{
printf("delete record error :%s\n", errmsg);
exit (-1);
}
}
}
void * read_client(void *arg)
{
int nbytes;
int new_fd = *((int *)arg);
struct message *msg = (struct message *)malloc(sizeof(struct message));
while((nbytes=read(new_fd,msg,sizeof(struct message))) > 0)
{
switch(msg->action)
{
case 1:/*注册*/
{
if((strcmp(msg->passwd,msg->to_msg)==0)&&(find_anode(msg->name)==NULL))/*两次输入的密码一致时*/
{
struct all *ptr = (struct all *)malloc(sizeof(struct all));/*将注册人员名单放入全体成员链表*/
memset(ptr,0,sizeof(struct all));
printf("register ok!\n");
strcpy(ptr->name,msg->name);
strcpy(ptr->passwd,msg->passwd);
msg->action = -1;
insert_record(msg);/*先放到数据库里面用来派出出现重复帐号的情况*/
insert_anode(ptr);/*再放到在线乘员链表中*/
write(new_fd,msg,sizeof(struct message));
break;
}
else
{
msg->action=1;
write(new_fd,msg,sizeof(struct message));
break;
}
}
case 2:/*登录*//*重复登录已解决*/
{
struct all *N=find_anode(msg->name);/*在全体人员里面找是否有则么一个人找到返回结构题指针*/
struct online *P=find_onode(msg->name);/*在上线成员链表里面找是否已经上线*/
if((N==NULL)||(P!=NULL))
{
printf("unregistered or logged in.\n");
msg->action = 0;
write(new_fd,msg,sizeof(struct message));
}
else if(strcmp(N->passwd,msg->passwd)!=0)
{
printf("Password input error,please input again\n");
msg->action=-201;
msg->length=new_fd;
write(new_fd,msg,sizeof(struct message));
}
else if((strcmp(N->passwd,msg->passwd)==0))/*找到并匹配密码,若正确*/
{
struct online *ptr = (struct online *)malloc(sizeof(struct online));/*创建在线成员的结构体*/
memset(ptr,0,sizeof(struct online));
printf("login ok!\n");
strcpy(ptr->name,N->name);
strcpy(ptr->passwd,N->passwd);
ptr->fd = new_fd;/*登录了以后每个成员都会有自己的fd了0*/
insert_onode(ptr);/*放入在线成员链表中*/
msg->action = -2;
write(new_fd,msg,sizeof(struct message));
}
else
{
printf("filure\n");
msg->action=0;
}
//write(new_fd,msg,sizeof(struct message));
break;
}
case 3:/*私聊*/
{
struct online *N=NULL;
N=find_onode(msg->to_name);/*从在线成员链表中查找*/
if(N!=NULL)
{
char sendtime[20]={'\0'};
get_time(sendtime);/*当前的时间以字符串形式存放在sendtime中*/
char buffer[1024];
memset(buffer,'\0',1024);
char *ptr=buffer;
/*strcpy(ptr,"siliao\n");
ptr+=strlen("siliao\n");*/
strcpy(ptr,sendtime);
ptr+=strlen(sendtime);/*指向发送者姓名的后米哪一个位置*/
*ptr++=']';
strcpy(ptr,msg->name);
ptr+=strlen(msg->name);
strcpy(ptr," send to ");
ptr+=strlen(" send to ");
strcpy(ptr,msg->to_name);
ptr+=strlen(msg->to_name);
*ptr++=':';
strcpy(ptr,msg->to_msg);
ptr+=strlen(msg->to_msg);
*ptr++='\n';/*buffer区的内容已经写好*/
ptr=buffer;
printf("read message!\n");
write(fd,ptr,strlen(ptr));
msg->action=-3;
write(N->fd,msg,sizeof(struct message));/*要交互信息的fd*/
}
else
{
printf("the one you want to message is not online\n");
}
break;
}
case 4:/*群聊*/
{
struct online *N=NULL;
N=ohead;/*从头节点一次遍历下去,给每一个在线成员发消息*/
char buffer[1024];
memset(buffer,'\0',1024);
char *ptr=buffer;
/*strcpy(ptr,"qunliao\n");
ptr+=strlen("qunliao\n");*/
char sendtime[20]={'\0'};
get_time(sendtime);/*当前的时间以字符串形式存放在sendtime中*/
strcpy(ptr,sendtime);
ptr+=strlen(sendtime);/*指向发送者姓名的后米哪一个位置*/
*ptr++=']';
strcpy(ptr,msg->name);
ptr+=strlen(msg->name);
strcpy(ptr," send to ");
ptr+=strlen(" send to ");
strcpy(ptr,"all");
ptr+=strlen("all");
*ptr++=':';
strcpy(ptr,msg->to_msg);
ptr+=strlen(msg->to_msg);
*ptr++='\n';/*buffer区的内容已经写好*/
ptr=buffer;
write(fd,ptr,strlen(ptr));
while(N!=NULL)
{
strcpy(msg->to_name,N->name);
printf("read message!\n");
msg->action=-3;
write(N->fd,msg,sizeof(struct message));/*要交互信息的fd*/
N=N->next;
}
if (N!=NULL)
{
printf("not all recv message\n");
}
break;
}
case 5:/*在线人员名单*/
{
struct online *N=NULL;
N=ohead;/*在线成员表头*/
printf("%d\n",N);
while(N!=NULL)
{
printf("read message!\n");
msg->action=-5;
strcpy(msg->to_name,N->name);
write(new_fd,msg,sizeof(struct message));/*发送消息的fd*/
N=N->next;
}
if (N!=NULL)
{
printf("not all recv message\n");
}
break;void insert_record(struct message *msg)/*将注册的新成员放入数据库中*/
{
sqlite3_open("mydatabase.db",&db);
char sql[100];
char *errmsg;
int ret;
sprintf(sql,"insert into mytable (name, passwd) values ('%s','%s' );", msg->name, msg->passwd);/*把中间这一串字符放入到sql中*/
ret = sqlite3_exec(db, sql, NULL, NULL, &errmsg);/*执行将之放入数据库的操作*/
if(ret != SQLITE_OK)
{
printf("insert record error :%s\n", errmsg);
return;
}
sqlite3_close(db);
return;
}
}
case 6:/*在线人员个数*/
{
msg->length=length_online();
msg->action=-6;
write(new_fd,msg,sizeof(struct message));
break;
}
case 7:/*离线人员个数*/
{
msg->length=(length_all()-length_online());
msg->action=-7;
write(new_fd,msg,sizeof(struct message));
break;
}
case 8:/*离线人员名单*/
{
int flag=0;
struct all *p1=ahead;
struct online * p2=ohead;
while(p1!=NULL)
{
flag=0;
p2=ohead;
while(p2!=NULL)
{
if(strcmp(p1->name,p2->name)==0)
{
flag=1;
break;
}
p2=p2->next;
}
if(flag==0)
{
msg->action=-8;
strcpy(msg->to_name,p1->name);
write(new_fd,msg,sizeof(struct message));
}
p1=p1->next;
}//close(fd);
break;
}
case 9:/*下线*/
{
delete_online(msg->name);/*服务器端已经把他从在线成员链表删除*/
msg->action=-9;
msg->length=new_fd;
write(new_fd,msg,sizeof(struct message));
break;
}
case 10:/*注销*/
{
delete_online(msg->name);/*从在线成员链表中删除*/
delete_all(msg->name);/*从所有成员那链表中删除*/
delete_record(msg->name);/*从数据库中删除*/
msg->action=-10;
msg->length=new_fd;
write(new_fd,msg,sizeof(struct message));
break;
}
case 11:/*获取管理员权限*/
{
msg->admin=1;
msg->action=-11;
printf("Access to administrator privileges!\n");
write(new_fd,msg,sizeof(struct message));
break;
}
case 12:
{
struct online *N=find_onode(msg->to_name);/*找到你想要禁言的人*/
msg->chat=0;/*用于暂存发言标志为,并不会改变自己的发言属性*/
msg->action=-13;/*用于向被禁言的人传递他已经被禁言这个消息*/
write(N->fd,msg,sizeof(struct message));/*将被禁言的人的标志位改为0*/
msg->chat=1;
msg->action=-12;/*用于想管理原返回他已经成功禁言某人*/
write(new_fd,msg,sizeof(struct message));/*改回原来的之以防影响原开得标志位*/
printf("jin yan cheng gong \n");/**/
break;
}
case 13:
{
struct online *N=find_onode(msg->to_name);
msg->chat=1;
msg->action=-15;
write(N->fd,msg,sizeof(struct message));/*用于解除被禁言的人的封印*/
msg->action=-14;
write(new_fd,msg,sizeof(struct message));/*告诉管理原他已经解禁成员成功*/
break;
}
case 14:
{
struct online *N=find_onode(msg->to_name);
msg->action=-16;
strcpy(msg->to_msg,msg->name);
write(N->fd,msg,sizeof(struct message));
msg->action=-17;
strcpy(msg->to_msg,msg->to_name);
break;
}
case 15:/*改密码,当然只能改他自己的这也是上线以后才能进行的操作*/
{
struct online *N=find_onode(msg->name);/*从上线成员链表中找到自己*/
struct all *A=find_anode(msg->name);/*从全体成员链表中找到自己*/
if((N!=NULL)&&(A!=NULL))
{
if(strcmp(N->passwd,msg->passwd)==0)
{
printf("password is correct\n");
strcpy(N->passwd,msg->to_msg);/*改在线成员链表的对应成员的密码*/
strcpy(A->passwd,msg->to_msg);/*更改全体成员链表里面的对应成员的密码*/
update_record(msg);
msg->action=-18;
printf("Change password success\n");/*告诉在线成员他已更该密码成功*/
write(new_fd,msg,sizeof(struct message));
}
else
{
msg->action=-19;
printf("The two passwords are different\n");
write(new_fd,msg,sizeof(struct message));
}
}
else
{
printf("You are not registered or logged in\n");
msg->action=-20;
write(new_fd,msg,sizeof(struct message));
}
break;
}
}
}
}
int main(int argc, char *argv[])
{
int rc;
rc = sqlite3_open("mydatabase.db", &db);/*若数据库存在打开数据库,不存在,先创建在打开数据库*/
if(rc != SQLITE_OK)
{
printf("can not open datatbase!\n");
exit (-1);
}
else/*创建成功*/
printf(" open datatbase sucess!\n");
rc=15;
rc = sqlite3_open("chatrecord.db", &db1);/*若数据库存在打开数据库,不存在,先创建在打开数据库*/
if(rc != SQLITE_OK)
{
printf("can not open datatbase!\n");
exit (-1);
}
else/*创建成功*/
printf(" open datatbase sucess!\n");
create_table(db);/*数据库里面建表*/
create_tablec(db1);/*数据库里面件表用于存放聊天记录*/
inquire_nocb(db);/*将数据库里面表的内容放入链表*/
over_anode();/*检查是否放好*/
if((fd=open("record4.txt",O_CREAT|O_RDWR,0755))<0)
{
printf("create .txt wenjian shibai \n");
}
pthread_t id;
int sockfd,new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size;
int ret;
int nbytes;
char buffer[1024];
int opt = 1; /* 套接字选项 */
//ahead = NULL;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
exit(1);
}
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(portnumber);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit(1);
}
if(listen(sockfd,5)==-1)
{
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
exit(1);
}
while(1)
{
sin_size=sizeof(struct sockaddr_in);
if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); // 将网络地址转换成.字符串
ret = pthread_create(&id,NULL,(void *)read_client,(void *)&new_fd);
if(ret)
{
printf("pthread error!\n");
}
}
sqlite3_close(db);
sqlite3_close(db1);
/* 结束通讯 */
close(fd);
close(sockfd);
exit(0);
}
客户端部分
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#define portnumber 3333
int admin=0;/*默认不是管理员*/
int chat=1;/*默认可以发言*/
int line=0;
struct message
{
char name[100];
char passwd[100];
char to_name[100];
char to_msg[100];
int admin;/*管理员标志位*/
int chat;/*发言标志位*/
int length;
int action;
};
void welcome()
{
printf("\t\t/*welcome to my mimi_chat!*/\n");
printf("\t\t/**input log login**/\n");
printf("\t\t/**input reg register**/\n");
printf("\t\t/***input sto send to one**/\n");
printf("\t\t/**input sta send to all**/\n");
printf("\t\t/**input online send to all online**/\n");
printf("\t\t/***input offonline send to all offonline**/\n");
printf("\t\t/***input cheakall send to all online number**/\n");
printf("\t\t/***input offonline send to all offonline number**/\n");
printf("\t\t/**input exit eixt system**/\n");
}
void * read_server(void *arg)/*线程调用函数*/
{
int fd = *((int *)arg);
int nbytes;
struct message *msg = (struct message *)malloc(sizeof(struct message));
while((nbytes=read(fd,msg,sizeof(struct message))) > 0)
{
switch(msg->action)
{
case -1:/*注册成功*/
{
printf("Register success\n");
break;
}
case 1:/*告诉成员他在注册时两次输入的密码不一致,所以注册失败*/
{
printf("The two passwords are different and the registration\n");
break;
}
case -2:/*登录成功*/
{
printf("Login success\n");
line=1;
break;
}
case -201:/*密码输入不正确,需要重新进入输入密码的界面,怎么进呢*//*要不在开一条线程*/
{
printf("Password input error,login failed\n");
break;
}
case 0:/*没注册或已经登录*/
{
printf("Unregistered or logged in.\n");
break;
}
case -3:/*接受来自他人的聊天信息*/
{
printf("Send from : %s\nmessage: %s\n",msg->name,msg->to_msg);
break;
}
case -4:/*告诉客户端,他的消息发送成功*/
{
printf("send ok\n");
break;
}
case -5:/*在线人员*/
{
printf("online :%s\n",msg->to_name);
break;
}
case -6:/*在线人员的个数*/
{
printf("online number is:%d\n",msg->length);
break;/*msg->admin=admin先走这边再走线程函数所以在*/;
}
case -7:/*离线人员的个数*/
{
printf("offline number is:%d\n",msg->length);
break;
}
case -8:/*离线人员的名单*/
{
printf("offline :%s\n",msg->to_name);
break;
}
case -9:/*下线成功*/
{
printf("offline success\n");
close(msg->length);
exit(0);
break;
}
case -10:/*注销成功*/
{
printf("Cancellation of success\n");
close(msg->length);
exit(0);
break;
}
case -11:/*获取管理员成功*/
{
printf("Access to administrator privileges!\n");
admin=msg->admin;
break;
}
case -12:/*告诉管理员禁言成员成功*/
{
printf("Banned success \n");
break;
}
case -13:/*告诉在线成员,他已经被禁言*/
{
chat=msg->chat;
printf("You have been bandned\n");
break;
}
case -14:/*告诉管理员解除成员禁言成功*/
{
printf("Banned success\n");
break;
}
case -15:/*告诉成员他已经被解除禁言*/
{
chat=msg->chat;
printf("Banned lift\n");
break;
}
case -16:/*告诉成员他已经被谁踢出聊天室*/
{
printf("You have been kicked out of the chat room by %s \n",msg->to_msg);
close(msg->length);
exit(0);
break;
}
case -17:/*告诉管理员他已经将某某成员踢出聊天室成功*/
{
printf("You have kicked %s out of the chat room\n",msg->to_msg);
break;
}
case -18:/*告诉在线成员他已更该密码成功*/
{
printf("Change password success\n");
break;
}
case -19:/*告诉成员更该密码失败,原因是因为两次密码输入不一致*/
{
printf("The two passwords are different\n");
break;
}
case -20:/*应该用不到*/
{
printf("You are not registered or logged in\n");
break;
}
default:
{
printf("something maybe error\n");
break;
}
}
}
}
int main(int argc, char *argv[])
{
int sockfd;
char buffer[1024];
struct sockaddr_in server_addr;
struct hostent *host;
pthread_t id;
struct message *msg = (struct message *)malloc(sizeof(struct message));
if(argc!=2)
{
fprintf(stderr,"Usage:%s hostname \a\n",argv[0]);
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"Gethostname error\n");
exit(1);
}
/* 客户程序开始建立 sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:Internet;SOCK_STREAM:TCP
{
fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));/**/
exit(1);
}
/* 客户程序填充服务端的资料 */
bzero(&server_addr,sizeof(server_addr)); // 初始化,置0
server_addr.sin_family=AF_INET; // IPV4
server_addr.sin_port=htons(portnumber); // (将本机器上的short数据转化为网络上的short数据)端口号
server_addr.sin_addr=*((struct in_addr *)host->h_addr); // IP地址
//welcome();
/* 客户程序发起连接请求 */
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
exit(1);
}
pthread_create(&id,NULL,(void *)read_server,(void *)&sockfd);/*线程*/
char input[1024];
welcome();
// read(sockfd,msg,sizeof(struct message));
/* 发送数据 */
while(1)
{
printf("Please input command:\n");
memset(input,0,1024);
scanf("%s",input);
if(strcmp(input,"reg") == 0)/*注册用户用户名只能是未注册过的*/
{
msg->action = 1;
printf("Please input name:\n");/*需要改进的功能:在输入帐号的时候就判别这个帐号有没有被注册,若有就直接返回,不用输入密码*/
scanf("%s",msg->name);
printf("Please input password:\n");
scanf("%s",msg->passwd);
printf("Please input you password again\n");
scanf("%s",msg->to_msg);
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"log") == 0)/*登录,只能登录未上线的用户*/
{
msg->action = 2;
printf("Please input name you want to log:\n");
scanf("%s",msg->name);
chat=1;/*默认可以聊天*/
printf("Please input true passwd:\n");
scanf("%s",msg->passwd);
write(sockfd,msg,sizeof(struct message));
}
if(line==1)/*登录以后才能涉及的功能*//*可是第一遍登录的时候标志为尚未来得及被改变*/
{
if(strcmp(input,"sto") == 0)
{
if(chat==1)
{
getchar();
msg->action = 3;/*本身的结构题里面有数据,方的是他的帐号和密码*/
printf("Please input to name:\n");
gets(msg->to_name);
while(1)
{
printf("Please input to message:\n");
gets(msg->to_msg);
if(strcmp(msg->to_msg,"over")==0)
{
break;
}
write(sockfd,msg,sizeof(struct message));
}
}
else
{
printf("ni yi jing bei jing yan\n");
}
}
if(strcmp(input,"sta") == 0)
{
if(chat==1)
{
getchar();
msg->action = 4;
while(1)
{
printf("Please input to message:\n");
gets(msg->to_msg);
if(strcmp(msg->to_msg,"over")==0)
{
break;
}
write(sockfd,msg,sizeof(struct message));
}
}
else
{
printf("ni yi jing bei jin yan \n");
}
}
if(strcmp(input,"online")==0)
{
msg->action=5;
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"cheakonline")==0)
{
msg->action=6;
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"cheakall")==0)
{
msg->action=7;
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"offline")==0)
{
msg->action=8;
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"downline")==0)
{
msg->action=9;
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"cancell")==0)
{
msg->action=10;
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"admin")==0)/*获取管理员权限*///暂时搁置管理员系统
{
msg->action=11;
write(sockfd,msg,sizeof(struct message));
//msg->admin=admin;/*先走这边再走线程函数所以在*/;
}
if(admin==1)/*管理员才能涉及的部分*/
{
if(strcmp(input,"jinyan")==0)
{
msg->action=12;
printf("Please input who you want to jinyan \n");
scanf("%s",msg->to_name);
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"jiejin")==0)
{
msg->action=13;
printf("Please input who you wang to jiejin\n");
scanf("%s",msg->to_name);
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"tiren")==0)
{
msg->action=14;
printf("Please input who you want to ta li kai liao tian shi\n");
scanf("%s",msg->to_name);
write(sockfd,msg,sizeof(struct message));
}
}
if(strcmp(input,"gaimima")==0)
{
msg->action=15;
printf("Please input old passwd\n");/*输入老密码,匹配正确后方可更改密码*/
scanf("%s",msg->passwd);
printf("please input new passwd\n");/*输入新密码*/
scanf("%s",msg->to_msg);
write(sockfd,msg,sizeof(struct message));
}
if(strcmp(input,"exit") == 0)
{
exit(0);
}
}
else
{
printf("ni hai mei deng lu ,bu neng jin xing qi ta cao zuo\n");
}
}
/* 结束通讯 */
close(sockfd);
exit(0);
}