服務(wù)器
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#define LOGIN 1
#define REGISTER 2
#define QUIT 3
typedef struct data //定義結(jié)構(gòu)體,保存用戶信息友存,用于登錄時(shí)檢驗(yàn)登陸的合法性
{
char name[20];
char passwd[20];
struct data *next;
}DATA,*PDATA;
typedef struct node //定義結(jié)構(gòu)體,保存在線用戶信息
{
char OnlineName[20];
int sockfd;
char Msg[100];
struct node *next;
}NODE,*PNODE;
void LoadDataFromList(PDATA head) //從文本中加載用戶信息
{
FILE *fp=fopen("Userlist.txt","r+");
if(NULL==fp)
{
printf("open is failed!\n");
exit(0);
}
DATA data;
while(1==fread(&data,sizeof(DATA),1,fp)) //讀取按數(shù)值來讀取,不可以定義指針來讀取
{
PDATA temp=(PDATA)malloc(sizeof(DATA));
strcpy(temp->name,data.name);
strcpy(temp->passwd,data.passwd);
temp->next=head->next;
head->next=temp;
}
fclose(fp);
fp=NULL;
}
void SaveDataToList(PDATA head) //對(duì)于新注冊(cè)的用戶,記錄到文本文件中
{
FILE *fp=fopen("Userlist.txt","w+");
if(fp==NULL)
{
printf("open is failed!\n");
exit(0);
}
PDATA p=head->next;
DATA data;
while(p)
{
strcpy(data.name,p->name);
strcpy(data.passwd,p->passwd);
fwrite(&data,sizeof(DATA),1,fp); //寫入時(shí)直奋,只能以數(shù)據(jù)形式寫入雄坪,不能用指針鏈表寫入
p=p->next;
}
fclose(fp);
fp=NULL;
}
void Login(int connfd,char name[])
{
int commond=-1;
char newName[20]={'\0'};
char passwd[20]={'\0'};
PDATA head = (PDATA)malloc(sizeof(DATA));
head->next=NULL;
LoadDataFromList(head);
do
{
PDATA p=head->next;
read(connfd,&commond,sizeof(int));
if(commond==LOGIN)
{
read(connfd,newName,sizeof(newName));
read(connfd,passwd,sizeof(passwd));
while(p!=NULL)
{
if(!strcmp(p->name,newName) && !strcmp(p->passwd,passwd))
{
write(connfd,"allow",20);
strcpy(name,newName);
return;
}
p=p->next;
}
write(connfd,"deny",20);
continue;
}
else if(commond==REGISTER)
{
read(connfd,newName,sizeof(newName));
read(connfd,passwd,sizeof(passwd));
while(p)
{
if(!strcmp(p->name,newName)) //判斷新注冊(cè)的用戶和系統(tǒng)原用戶不重名
{
write(connfd,"deny",20);
}
p=p->next;
}
PDATA q=(PDATA)malloc(sizeof(DATA));
q->next=head->next;
head->next=q;
strcpy(q->name,newName);
strcpy(q->passwd,passwd);
SaveDataToList(head);
write(connfd,"allow",20);
}
else if(commond==QUIT)
{
close(connfd);
break;
}
}while(1);
}
void *chatroom(void *arg)
{
PNODE headGroup=(PNODE) arg;
do
{
sleep(1);
PNODE t=headGroup->next;
while(t)
{
if(read(t->sockfd,t->Msg,sizeof(t->Msg))>0)
{
printf("t->Msg:%s\n",t->Msg);
char MSG[100]={'\0'};
strcat(MSG,t->OnlineName);
strcat(MSG,":");
strcat(MSG,t->Msg);
PNODE s=headGroup->next;
while(s)
{
write(s->sockfd,MSG,sizeof(MSG));
s=s->next;
}
printf("t->sockfd=%d\n",t->sockfd);
sleep(1);
}
t=t->next;
}
}while(1);
}
int main()
{
int listenfd = -1;
int connfd = -1;
int i = 0;
int j = 0;
char name[20]={'\0'};
char MsgName[100]={0};
char Div[]="/";
PNODE head=(PNODE)malloc(sizeof(NODE));
head->next=NULL;
socklen_t clilen = 0;
struct sockaddr_in cliaddr = {0};
struct sockaddr_in servaddr = {0};
int ret = 0;
listenfd = socket(AF_INET, SOCK_STREAM, 0); //開啟套接口
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_aton("127.0.0.1", &(servaddr.sin_addr));
servaddr.sin_port = htons(5678);
ret = bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
ret += listen(listenfd, 5);
while(1)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("CLient Ip:%s\n",inet_ntoa(cliaddr.sin_addr));
Login(connfd,name); //這里將空名字傳入,在函數(shù)里將讀到的名字賦予這個(gè)指針嘲恍,方便后用
printf("%s log in\n",name);
PNODE p=(PNODE)malloc(sizeof(NODE));
strcpy(p->OnlineName,name); //將登陸成功的用戶名加入在線鏈表 中
p->sockfd=connfd;
p->next=head->next;
head->next=p;
PNODE q=head->next;
memset(MsgName,0,sizeof(MsgName));
while(q)
{
strcat(MsgName,q->OnlineName); //遍歷鏈表,strcat函數(shù)將所有的在線用戶名連在一起雄驹,用Div分隔符分隔開佃牛,傳給客戶端
strcat(MsgName,Div);
q=q->next;
}
write(connfd,MsgName,sizeof(MsgName));
printf("234: %s\n",MsgName);
memset(MsgName,0,sizeof(MsgName));
int test = read(connfd,MsgName,sizeof(MsgName));
printf("MsgName=%s\n",MsgName);
char *OnlineName=NULL;
OnlineName=strtok(MsgName,Div); //strtok函數(shù)將客戶端傳來的字符串拆開,定義了字符串是以“/”隔開的
q=head->next;
PNODE t=(PNODE)malloc(sizeof(NODE));
PNODE headGroup=(PNODE)malloc(sizeof(NODE));
headGroup->next=NULL;
while(OnlineName!=NULL)
{
while(q)
{
if(!strcmp(q->OnlineName,OnlineName))
{
t=q;
t->next=headGroup->next;
headGroup->next=t;
}
q=q->next;
}
OnlineName=strtok(NULL,Div);
}
int retpth=-1;
pthread_t thread;
retpth=pthread_create(&thread,NULL,chatroom,(void *)headGroup);
if(retpth!=0)
{
perror("pthread");
return -1;
}
}
close(listenfd);
CloseAllClientFdFromArr(arrfd,NUM_FD);
return 0;
}
客戶端
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#define LOGIN 1
#define REGISTER 2
#define QUIT 3
typedef struct data
{
char name[20];
char passwd[20];
struct data *next;
}DATA,*PDATA;
typedef struct node
{
char OnlineName[20];
int sockfd;
char Msg[100];
struct node *next;
}NODE,*PNODE;
void handler(int sig)
{
if(SIGINT ==sig) //信號(hào):監(jiān)測(cè)到ctrl+c時(shí)執(zhí)行退出命令
{
printf("Thank you for use!\n");
exit(0);
}
}
void LoadData(PDATA head)
{
printf("Input your username:");
scanf("%s%*c",head->name);
system("stty -echo"); //密碼隱藏:關(guān)閉顯示器顯示医舆,待密碼輸入結(jié)束時(shí)再重新開啟
printf("Input your password:");
scanf("%s%*c",head->passwd);
system("stty echo");
}
void chatroom(int sockfd)
{
char MsgName[100]={'\0'};
read(sockfd,MsgName,sizeof(MsgName));
printf("Online people are %s\n Input names to chat:",MsgName);
memset(MsgName,0,sizeof(MsgName));
scanf("%s%*c",MsgName);
int test = write(sockfd,MsgName,sizeof(MsgName));
printf("58: test = %d\n",test);
printf("Start chatting\n");
char MSG[100]={'\0'};
while(1)
{
if(scanf("%[^\n]s",MSG)>0) //[^\n]從鍵盤緩存區(qū)中不斷讀入俘侠,直到回車鍵
{
write(sockfd,MSG,sizeof(MSG))>0;
}
if(read(sockfd,MSG,sizeof(MSG))>0)
{
printf("%s\n",MSG);
}
sleep(1);
}
}
int main(int argc, char *argv[])
{
signal(SIGINT,handler);
int sockfd;
struct sockaddr_in servaddr;
int ret = 0;
int commond=-1;
char name[20]={'\0'};
char passwd[20]={'\0'};
char feedback[20]={'\0'};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5678);
inet_aton("127.0.0.1", &servaddr.sin_addr);
ret = connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if(ret < 0)
{
perror("connect");
close(sockfd);
return 1;
}
while(1)
{
printf("Welcome to the system\n Select one to continue:\n");
printf("1.Log in\t2.Register\t3.quit\n");
scanf("%d%*c",&commond);
write(sockfd,&commond,sizeof(int));
if(commond == QUIT)
{
break;
}
PDATA head=(PDATA)malloc(sizeof(DATA));
head->next=NULL;
LoadData(head);
strcpy(name,head->name);
strcpy(passwd,head->passwd);
write(sockfd,name,sizeof(name));
write(sockfd,passwd,sizeof(passwd));
read(sockfd,feedback,20);
if(commond ==LOGIN)
{
if(!strcmp(feedback,"allow"))
{
chatroom(sockfd);
printf("========\n");
getchar();
}
else if(!strcmp(feedback,"deny"))
{
printf("Wrong username or password\n");
continue;
}
}
else if(commond==REGISTER)
{
if(!strcmp(feedback,"allow"))
{
printf("Register in\n");
}
else if(!strcmp(feedback,"deny"))
{
printf("Confict username,try again!\n");
}
continue;
}
}
close(sockfd);
return 0;
}