⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.c

📁 linux下用C语言写的聊天程序!/*BUG and NOTE: Not join protect to Shared Memory Segments,example Semaphore Array
💻 C
字号:
/*    SeaRobberStudio    */
/*BUG and NOTE:
Not join protect to Shared Memory Segments,example Semaphore Arrays.
Not check the parameters validity.
When transmit may be error.
If the client program no right exit,others cannot know,the service program should be check the client program whether exist timing.
The program when exit(), it do not delete the Shared Memory Segments,you maybe use at exit() but the program have some processes.
When one process is exit(),others is continue.
The service program's action is few.
And so on. */
/*   !print:  print clients message.
 !all:message broadcast message. */
/* programname  serviceip  yourname  key */
#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 <sys/ipc.h>
#include <sys/shm.h>
#include <arpa/inet.h>
#include <signal.h>

#define WAITBUF 10
#define PORT 1984
#define CLIENTNUMBER 10
#define SHM_KEY 84
#define CLIENTPORT 2006
#define RECVIPPORT 2008

struct client{
    char name[13];
    char ip[16];
    int count;
    int state;
};
struct clientmsg{
    char name[12];
    char ip[16];
    int state;
};

void AddToClient(struct client *clients,int numbers,struct clientmsg clientmsg);
void PrintClient(struct client *clients,int numbers);
int NameToIp(struct client *clients,int numbers,char *name,char *ip);
void SendToEveryone(struct client *clients,int numbers,int sockfd,int port,struct clientmsg clientmsg);
void DeleteToClient(struct client *clients,int numbers,struct clientmsg clientmsg);
int IpToName(struct client *clients,int numbers,char *name,char *ip);
void SendMsgToEveryone(struct client *clients,int numbers,int sockfd,int port,char *msg);
void sigfunc(int signo);

static struct client *clients;
static struct clientmsg clientmsg;
static char serviceip[16];
static int seg_id; 
int main(int argc, char *argv[])
{
    int sockfd,new_fd,sockfdip;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    struct sockaddr_in send_addr,recv_addr;
    int recv_len;
    int addr_len;
    int count=0;
    int i;
    int sin_size;
    pid_t recvpid;
    pid_t recvippid;
    char *mem_ptr;
    char hostname[30];
    struct hostent *hp;
    int key;
    char msg_buf[BUFSIZ];
    char sendname[13];
    char sendip[16];
    char recvname[13];
    char recvip[16];
    char *sendmsg;
    struct sigaction act; 
   
    if(argc != 4)
    {
     printf("parameter must like: command ip name key\n");
 exit(1);
    }
    if(argv[3][0] == '!')
    {
     printf("the first letter of name isnot '!'\n");
 exit(1);
    }
    if(strlen(argv[3]) > 10)
    {
     printf("the length of name is not more then 10 ");
 exit(1);
    }
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        fprintf(stderr,"Socket error:%s\n",strerror(errno));
        exit(1);
    }
    strncpy(serviceip,argv[1],16);
// printf("service :%s",serviceip);
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=inet_addr(argv[1]);
    server_addr.sin_port=htons(PORT);
    if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)) == -1)
    {
     fprintf(stderr,"Connect error:%s\n",strerror(errno));
 exit(1);
    } 
    key=atoi(argv[3]);
    seg_id=shmget(key,sizeof(struct client)*CLIENTNUMBER,IPC_CREAT | 0600);
    if(seg_id == -1)
    {
     perror("shmget");
 exit(1);
    }
    clients=(struct client *)shmat(seg_id,NULL,0);
    for(i=0; i<CLIENTNUMBER; i++)
    {
        clients[i].state=0;
 clients[i].count=0;
    }
     gethostname(hostname,30);
 hp=gethostbyname(hostname);
 inet_ntop(AF_INET,hp->h_addr,clientmsg.ip,16);
     strncpy(clientmsg.name,argv[2],11);
 clientmsg.state=1;
 if(send(sockfd,&clientmsg,sizeof(struct clientmsg),0) != sizeof(struct clientmsg))
 {
  fprintf(stderr,"send error:%s\n",strerror(errno));
  exit(1);
 }
 if(recv(sockfd,clients,sizeof(struct client)*CLIENTNUMBER,0) == -1)
 {
  fprintf(stderr,"recv error:%s\n",strerror(errno));
  exit(1);
 }
 close(sockfd);
 PrintClient(clients,CLIENTNUMBER);

    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
   {
         fprintf(stderr,"Socket error:%s\n",strerror(errno));
      exit(1);
     }
 if((recvpid=fork()) < 0)
 {
  fprintf(stderr,"fork error:%s\n",strerror(errno));
  exit(1);
 }
 if(recvpid == 0)
 {//recv
  bzero(&recv_addr,sizeof(struct sockaddr_in));
  recv_addr.sin_family=AF_INET;
  recv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  recv_addr.sin_port=htons(CLIENTPORT);
  if(bind(sockfd,(struct sockaddr*)(&recv_addr),sizeof(recv_addr)) == -1)
  {
   fprintf(stderr,"Bind error:%s\n",strerror(errno));
   exit(1);
  }
  addr_len=sizeof(recv_addr);
  
  while(1)
  {
   recv_len=recvfrom(sockfd,msg_buf,BUFSIZ,0,(struct sockaddr *)&recv_addr,&addr_len);
   msg_buf[recv_len]='\0';
   strncpy(recvip,inet_ntoa(recv_addr.sin_addr),16);
   IpToName(clients,CLIENTNUMBER,recvname,recvip);
   printf("%s say:%s\n",recvname,msg_buf);
  
  }//while(1)
 }//recv end
 if((recvippid=fork()) < 0)
 {
  fprintf(stderr,"fork error:%s\n",strerror(errno));
  exit(1);
 }
 if(recvippid == 0)
 {//recvip
     if((sockfdip=socket(AF_INET,SOCK_DGRAM,0))==-1)
    {
          fprintf(stderr,"Socket error:%s\n",strerror(errno));
       exit(1);
      }
  bzero(&recv_addr,sizeof(struct sockaddr_in));
  recv_addr.sin_family=AF_INET;
  recv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  recv_addr.sin_port=htons(RECVIPPORT);
  if(bind(sockfdip,(struct sockaddr*)(&recv_addr),sizeof(recv_addr)) == -1)
  {
   fprintf(stderr,"RecvIp Bind error:%s\n",strerror(errno));
   exit(1);
  }
  addr_len=sizeof(recv_addr);
  
  while(1)
  {
   recv_len=recvfrom(sockfdip,&clientmsg,sizeof(clientmsg),0,(struct sockaddr *)&recv_addr,&addr_len);
   if(clientmsg.state == 1)
   {
    AddToClient(clients,CLIENTNUMBER,clientmsg);
    printf("join name:%s\n",clientmsg.name);
   }
   else
   {
    DeleteToClient(clients,CLIENTNUMBER,clientmsg);
    printf("leave name:%s\n",clientmsg.name);
   }
  }//while(1)
  
 }//recvip end
 else
 {//send  //father fork
  SendToEveryone(clients,CLIENTNUMBER,sockfd,RECVIPPORT,clientmsg);
  act.sa_handler=sigfunc;
  sigemptyset(&act.sa_mask);
  sigaddset(&act.sa_mask,SIGINT);
  sigaddset(&act.sa_mask,SIGQUIT);
  act.sa_flags=0;
  if(sigaction(SIGINT,&act,NULL) < 0)
  {
   fprintf(stderr,"SIGINT error:%s",strerror(errno));
  }
  if(sigaction(SIGINT,&act,NULL) < 0)
  {
   fprintf(stderr,"SIGINT error:%s",strerror(errno));
  }
  
  while(1)
  {
   memset(msg_buf,0,sizeof(msg_buf));
   fgets(msg_buf,BUFSIZ,stdin);
   if((sendmsg=memchr(msg_buf,':',13)) == NULL)
   {
    printf("no name\n");
    continue;
   }
//   printf("|%s|\n",sendmsg);
   strncpy(sendname,msg_buf,sendmsg-msg_buf);
   sendname[sendmsg-msg_buf]='\0';
   if(strcmp(sendname,"!print") == 0)
   {
    PrintClient(clients,CLIENTNUMBER);
    continue;
   }
   sendmsg++;
   if(sendmsg == NULL)
   {
    printf("no message\n");
    continue;
   }
//   printf("name:%s,ip:%s,msg,%s!\n",sendname,sendip,sendmsg);
   if(strcmp(sendname,"!all") == 0)
   {
    SendMsgToEveryone(clients,CLIENTNUMBER,sockfd,CLIENTPORT,sendmsg);
    continue;
   }
   if(NameToIp(clients,CLIENTNUMBER,sendname,sendip) == -1)
   {
    printf("have no the name\n");
    continue;
   }
   bzero(&send_addr,sizeof(struct sockaddr_in));
       send_addr.sin_addr.s_addr=inet_addr(sendip);
       send_addr.sin_family=AF_INET;
     send_addr.sin_port=htons(CLIENTPORT);
   if(sendto(sockfd,sendmsg,strlen(sendmsg),0,(struct sockaddr *)&send_addr,sizeof(send_addr)) == -1)
   {
    fprintf(stderr,"send error:%s\n",strerror(errno));
   }
  }//while(1)
 }//send end
 
}
void sigfunc(int signo)
{
 int i;
 int sockfd;
     struct sockaddr_in send_addr;
 clientmsg.state=0;
    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
   {
         fprintf(stderr,"Socket error:%s\n",strerror(errno));
      exit(1);
     }
 SendToEveryone(clients,CLIENTNUMBER,sockfd,RECVIPPORT,clientmsg);
 bzero(&send_addr,sizeof(struct sockaddr_in));
     send_addr.sin_addr.s_addr=inet_addr(serviceip);
     send_addr.sin_family=AF_INET;
   send_addr.sin_port=htons(RECVIPPORT);
 if(sendto(sockfd,&clientmsg,sizeof(clientmsg),0,(struct sockaddr *)&send_addr,sizeof(send_addr)) == -1)
 {
  fprintf(stderr,"send error:%s\n",strerror(errno));
 }
 close(sockfd);
 if(shmctl(seg_id,IPC_RMID,NULL) == -1)
 {
  printf("unlink msg queue error\n");
 }
 if(signal(SIGINT,SIG_DFL) == SIG_ERR)
 {
  fprintf(stderr,"SIGINT SIG_DFL error:%s\n",strerror(errno));
  exit(1);
 }
 if(signal(SIGQUIT,SIG_DFL) == SIG_ERR)
 {
  fprintf(stderr,"SIGQUIT SIG_DFL error:%s\n",strerror(errno));
  exit(1);
 }
 kill(getpid(),signo);
}
void AddToClient(struct client *clients,int numbers,struct clientmsg clientmsg)
{
 int i,len,ch;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   if(strcmp(clients[i].name,clientmsg.name) == 0)
   {
    
    clients[i].count++;
    len=strlen(clients[i].name);
    if(clients[i].count < 10)
    {
     (clients[i].name)[len]=clients[i].count+48;
     (clients[i].name)[len+1]='\0';
    }
    if(clients[i].count > 9)
    {
     (clients[i].name)[len]=clients[i].count/10+48;
     (clients[i].name)[len+1]=clients[i].count%10+48;
     (clients[i].name)[len+2]='\0';
     
    }
    AddToClient(clients,numbers,clientmsg);
    clients[i].count=0;
    return ;
   }
  }
 }
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 0)
  {
   clients[i].state=1;
   strncpy(clients[i].name,clientmsg.name,13);
   strncpy(clients[i].ip,clientmsg.ip,16);
   clients[i].count=0;
   break;
  }
 }
}
void PrintClient(struct client *clients,int numbers)
{
 int i;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   printf("name:%s ip:%s\n",clients[i].name,clients[i].ip);
  }
 }
}
int NameToIp(struct client *clients,int numbers,char *name,char *ip)
{
 int i;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   if(strcmp(clients[i].name,name) == 0)
   {
    strncpy(ip,clients[i].ip,16);
    return 0;
   }
  }
 }
 return -1;
}
int IpToName(struct client *clients,int numbers,char *name,char *ip)
{
 static unnamenumber=0;
 int i;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   if(strcmp(clients[i].ip,ip) == 0)
   {
    strncpy(name,clients[i].name,13);
    return 0;
   }
  }
 }
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 0)
  {
   strncpy(clients[i].ip,ip,16);
   sprintf(clients[i].name,"unname%d",unnamenumber);
   clients[i].state=1;
   unnamenumber++;
   strncpy(name,clients[i].name,13);
   return 0;
  }
 }
}
void SendToEveryone(struct client *clients,int numbers,int sockfd,int port,struct clientmsg clientmsg)
{
 int i;
     struct sockaddr_in send_addr;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   bzero(&send_addr,sizeof(struct sockaddr_in));
       send_addr.sin_addr.s_addr=inet_addr(clients[i].ip);
       send_addr.sin_family=AF_INET;
     send_addr.sin_port=htons(port);
   if(sendto(sockfd,&clientmsg,sizeof(clientmsg),0,(struct sockaddr *)&send_addr,sizeof(send_addr)) == -1)
   {
    fprintf(stderr,"send error:%s\n",strerror(errno));
   }
  }
 }
}
void SendMsgToEveryone(struct client *clients,int numbers,int sockfd,int port,char *msg)
{
 int i;
     struct sockaddr_in send_addr;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   bzero(&send_addr,sizeof(struct sockaddr_in));
       send_addr.sin_addr.s_addr=inet_addr(clients[i].ip);
       send_addr.sin_family=AF_INET;
     send_addr.sin_port=htons(port);
   if(sendto(sockfd,msg,sizeof(msg),0,(struct sockaddr *)&send_addr,sizeof(send_addr)) == -1)
   {
    fprintf(stderr,"send error:%s\n",strerror(errno));
   }
  }
 }
}
void DeleteToClient(struct client *clients,int numbers,struct clientmsg clientmsg)
{
 int i;
 for(i=0; i<numbers; i++)
 {
  if(clients[i].state == 1)
  {
   if(strcmp(clients[i].ip,clientmsg.ip) == 0)
   {
    clients[i].state=0;
    return ;
   }
  }
 }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -