📄 scd.c
字号:
#include "scd.h"
//deal with client's request
void process_cli(int connectfd, struct sockaddr_in client);
//when server create a thread ,call this function
void * start_routine(void* arg);
//add a client into a list
int add_client(char cli_name[], int connfd, char hostname[]);
//delete a client from a list
void delete_client(char cli_name[]);
//recongnize the commands or send the common message to other clients
int processInput(char recvbuf[],int connectfd, char cli_name[]);
//send the message to all clients
void all_send(char cli_name[], char msg[]);
//change client's name for the command--"nick nickname"
int changeNickName(char cli_name[], char newname[], int connectfd);
//get all client's name for the command--"/who"
void getAllCli_Name();
//send the message to a special client
int one_send(char* tokenPtr, char cli_name[], char msg[]);
//get all clients who are connected to the server
void sendcli_list(int connectfd);
//check the parameter--"./scd [-i] [-m max] [-p port]"
int checkParam(int argc,char* argv[],int* isSecure,int* backlog,int* port);
//read the help file for command--"/help"
void ReadHelpFile(char cmdbuf[]);
//change a client's passwd for command--"/passwd"
int changePasswd(char cli_name[], char passwd[],int connectfd);
void decrypt(char sendbuf[], char passwd[]);
void mydecrypt(char sendbuf[], char passwd[]);
void myencrypt(char sendbuf[], char passwd[]);
int main(int argc,char * argv[])
{
int listenfd,connectfd;
pthread_t thread;
struct ARG *arg;
struct sockaddr_in server;
struct sockaddr_in client;
int sin_size;
int opt;
int isSecure,backlog,port;
isSecure=1;
backlog=0;
port=0;
if(checkParam(argc,argv,&isSecure,&backlog,&port)==0)
{
exit(1);
}
// printf("isSecure:%d\tbacklog:%d,\tport:%d\n",isSecure,backlog,port);
if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("Creating socket failed.");
exit(1);
}
//设置套接字选项为SO_REUSEADDR,即socket可重用
opt=SO_REUSEADDR;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
bzero(&server,sizeof(server));
//设置套接字地址
server.sin_family=AF_INET;
server.sin_port=htons((port==0)?PORT:port);
server.sin_addr.s_addr=htonl(INADDR_ANY); /*填入本机IP地址*/
/* 绑定:将套接字和地址信息相关连
函数原形:int bind(int s,const struct sockaddr * name,int namelength); */
if(bind(listenfd,(struct sockaddr*)&server,sizeof(struct sockaddr))==-1)
{
perror("Bind error.");
exit(1);
}
/* 监听操作由listen()实现,listenfd是套接字系统调用返回的套接字描述符
backlog指定在请求队列中等待服务请求的数目进行了限制 */
if(listen(listenfd,(backlog==0)?BACKLOG:backlog)==-1)
{
perror("listen() error."); //队列已满,拒绝连接请求
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
if((connectfd=accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1)
{
perror("accept() error\n");
exit(1);
}
/* 把连接套接字(connectfd)和客户地址信息(client)付给arg */
arg=malloc(sizeof(struct ARG));
arg->connfd=connectfd;
memcpy((void *)&arg->client,&client,sizeof(client));
if(pthread_create(&thread,NULL,start_routine,(void*)arg))
{
perror("Pthread_create() error");
exit(1);
}
}
close(listenfd);
}
void process_cli(int connectfd, struct sockaddr_in client)
{
int num,i,isCommand;
char hostname[30];
char cli_name[MAXDATASIZE], recvbuf[MAXDATASIZE];
isCommand=0;
//获取此客户机的IP地址
strcpy(hostname, inet_ntoa(client.sin_addr));
printf("You got a connection from %s. ", hostname);
//接收nickname
num=recv(connectfd,cli_name,MAXDATASIZE,0);
if(num==0)
{
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num]='\0';
//检验nickname是否已经被用
while(add_client(cli_name,connectfd,hostname)==0)
{
//send(connectfd,errbuf,strlen(errbuf),0); // send the error message
one_send(cli_name,cli_name,errbuf);
num=recv(connectfd,cli_name,MAXDATASIZE,0); // get the nickname again !
if(num==0)
{
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num-1]='\0';
}
printf("Client's name is %s.\n",cli_name);
//接收客户信息
while(num=recv(connectfd,recvbuf,MAXDATASIZE,0) )
{
recvbuf[num]='\0';
decrypt(recvbuf,cli_name); //解密
printf("Received client( %s ) message:%s\n",cli_name,recvbuf);
isCommand = processInput(recvbuf,connectfd,cli_name); //处理信息里可能有的命令
if(isCommand ==1 || isCommand==3 || isCommand==4 || isCommand==5 || isCommand==6)
{
continue; //do not send the command input
}
else if(isCommand ==2) //get the command----quit
{
delete_client(cli_name);
close(connectfd);
return;
}
all_send(cli_name,recvbuf); // send this message to all the clients
}
//客户已退出,所以删除此用户,并关闭连接
delete_client(cli_name);
close(connectfd);
}
void * start_routine(void * arg)
{
struct ARG *info;
info=(struct ARG *)arg;
process_cli(info->connfd,info->client); //处理此客户请求
free(arg);
pthread_exit(NULL); //结束本线程
}
//*************************************
int add_client(char cli_name[] , int connfd, char hostname[])
{
struct clientsInfo* a_client ;
struct clientsInfo* pcli;
pthread_mutex_lock(&a_mutex); //加锁
a_client = (struct clientsInfo*)malloc(sizeof(struct clientsInfo));
if(!a_client)
{
fprintf(stderr,"add_request: out of memory\n");
return 0;
}
memcpy(a_client->nickname,cli_name,NAMESIZE);
strcpy(a_client->hostname,hostname);
a_client->connectfd=connfd;
a_client->next = NULL;
if(clientsCount==0)
{
clients=a_client;
last_client=a_client;
}
else
{
pcli = clients;
while(pcli != NULL) // tranverse the list to make sure that no two nickname is the same
{
if(!strcmp(pcli->nickname,a_client->nickname))
{
pthread_mutex_unlock(&a_mutex); //解锁
return 0;
}
pcli = pcli->next;
}
last_client->next=a_client;
last_client = a_client;
}
clientsCount++;
pthread_mutex_unlock(&a_mutex); //解锁
return 1;
}
void delete_client(char cli_name[])
{
struct clientsInfo* pcli1;
struct clientsInfo* pcli2;
pthread_mutex_lock(&a_mutex); //加锁
if(clientsCount > 0)
{
pcli1 = clients;
pcli2 = clients;
if(!strcmp(pcli1->nickname,cli_name)) //find it in the first place
{
clients = clients->next;
if(last_client==NULL)
{
last_client = NULL;
}
clientsCount--;
pthread_mutex_unlock(&a_mutex); //解锁
return;
}
pcli1=pcli1->next;
while(pcli1 != NULL) // tranverse the list to find to nickname to delete
{
if(!strcmp(pcli1->nickname,cli_name)) //find it
{
pcli2->next=pcli1->next;
free(pcli1);
pcli1=pcli2->next;
if(last_client==NULL)
{
last_client = NULL;
}
clientsCount--;
pthread_mutex_unlock(&a_mutex); //解锁
return;
}
}
}
}
int processInput(char recvbuf[],int connectfd, char cli_name[])
{
int i;
char combuf[COMMANDSIZE];
char namechange[MAXDATASIZE];
char passwd[PASSWD];
char * tokenPtr;
char * tokenPtr2;
strcpy(combuf,recvbuf);
combuf[strlen(combuf)]='\0';
tokenPtr=(char *)strtok(combuf," ");
while(tokenPtr != NULL)
{
if(!strcmp(tokenPtr,"/quit"))
{
//send(connectfd,quitbuf,strlen(quitbuf),0); //send "byte!"
one_send(cli_name, cli_name, quitbuf);
return 2;
}
else if(!strcmp(tokenPtr,"/help"))
{
ReadHelpFile(cmdbuf);
//send(connectfd,cmdbuf,strlen(cmdbuf),0); //send the detail of command
one_send(cli_name, cli_name, cmdbuf);
return 1;
}
else if(!strcmp(tokenPtr,"/passwd"))
{
tokenPtr=(char *)strtok(NULL," ");
if(tokenPtr != NULL)
{
bzero(passwd,sizeof(passwd));
strcat(passwd,tokenPtr);
passwd[strlen(passwd)]='\0';
if(changePasswd(cli_name,tokenPtr,connectfd) !=1) //change success
{
send(connectfd,pwdbuf0,strlen(pwdbuf0),0); //send the error of command
return 0;
}
send(connectfd,pwdbuf1,strlen(pwdbuf1),0); //send the success of command
bzero(passwd,sizeof(passwd));
return 6;
}
else
{
send(connectfd,pwdbuf0,strlen(pwdbuf0),0); //send the error of command
return 0;
}
return 6;
}
else if(!strcmp(tokenPtr,"/m"))
{
tokenPtr=(char *)strtok(NULL," "); //获取信息的发送对象
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -