关闭

linux局域网通讯源码(服务器多路复用和客户端多进程模式)(socket)客户端

标签: socket服务器linux通讯listuser
1351人阅读 评论(1) 收藏 举报
分类:

/*client.c*/

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include<malloc.h>
//#include<curses.h>//linux图形化编程界面函数

#define PORT 4321
#define BUFFER_SIZE 1024

typedef struct user
{
   struct sockaddr_in users_sockaddr;//用户IP
   int user_fd;//用户连接套接字
   char *user_name;//用户别名
   char buf[BUFFER_SIZE];//用户发的信息
   char del[4];//删除下线用户信号标志位
   int rece_id;
   struct user *Next;
}USER_List,*pUSER_List;

pUSER_List craet_USER_listhead()
{
  pUSER_List pHead=(pUSER_List)malloc(sizeof(USER_List));
  if(pHead==NULL)
  {
   printf("The Dynamic memory allocation is fail\n");
   exit(-1);
  }
   pHead->Next=NULL;
   return pHead; 
}

pUSER_List craet_USER_buff()
{
 pUSER_List pbuff=(pUSER_List)malloc(sizeof(USER_List));
   if(pbuff==NULL)
   {
    printf("The Dynamic memory allocation is fail\n");
    exit(-1);
   }
   return pbuff; 
}


pUSER_List insert_USERList(pUSER_List p,struct sockaddr_in uaddr,int fd,char *name)
{
 int i=0;
 pUSER_List pNew=(pUSER_List)malloc(sizeof(USER_List));
 if(pNew==NULL)
   {
  printf("The Dynamic memory allocation is fail\n");
  exit(-1);
   }
 
   pNew->users_sockaddr=uaddr;
   pNew->user_fd=fd;

 while(p->Next)
 {
  p=p->Next;
 }
 
 p->Next=pNew;
 pNew->Next=NULL;
 
return;
}

void delet_List(pUSER_List p,int fd)
{
 pUSER_List q;
    do
 {
  q=p;//先保存前一个地址
  p=p->Next;
  if(p->user_fd==fd)
  {
        q->Next=p->Next;
  free(p);
  }
  
 }while(p->Next);
}


char * choosechatmode(int sockfd,char *c)
{   int sendbytes,fd;
 printf("Please choose the many people chat?or single people chat\n\n");
 printf("many people chat please input manp\n");
 printf("single people chat please input sinp\n");
  scanf("%s",c);
 while((strcmp("sinp",c)!=0)&&(strcmp("manp",c)!=0))
 {
    printf("Please input the correct command!!\n");
 scanf("%s",c);
 }
return c; 
}

void show_online_users_list(pUSER_List USER)
{
 printf("The online user list:--------------------------------\n");
   do
    {
   USER=USER->Next;
   printf("USER Socket is %d:",USER->user_fd);
   printf("  The USER IP:%s\n",(char*)inet_ntoa(USER->users_sockaddr.sin_addr));
    }while(USER->Next->Next);
  printf("******************************************************\n");
}

int chack_socket_number(pUSER_List USER,int fd)
{
  while(USER->Next)
  {
    if(USER->user_fd==fd)return 0;//说明上线用户列表中有这个用户
    USER=USER->Next;
  }
  printf("The socket number In the online_user list is not exit!!!\n");
  return 1;
}

int main(int argc, char *argv[])
{
 
    pUSER_List USER,zero;
 USER_List buff;
 USER_List rebuff;
 int recvbytes;
 int sockfd, sendbytes;
 struct hostent *host;
 struct sockaddr_in serv_addr;
 char c[10];
 USER=craet_USER_listhead();//创建用户列表文件?    zero=USER;
    zero=USER;
    pid_t child;
  int fd;
 /*地址解析函数*/
 if ((host = gethostbyname(argv[1])) == NULL)
 {
  perror("gethostbyname");
  exit(1);
 }

 /*创建socket*/
 if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
 {
  perror("socket");
  exit(1);
 }
 
 /*设置sockaddr_in 结构体中相关参数*/
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_port = htons(PORT);
 serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
 bzero(&(serv_addr.sin_zero), 8);
 
 /*调用connect函数主动发起对服务器端的连接*/
 if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1)
 {
  perror("connect");
  exit(1);
 }
 
    //接收用户在线用户列表
   while(1)
   {
    memset(&buff,0,sizeof(USER_List));
    if ((recvbytes = recv(sockfd, &buff, sizeof(USER_List), 0)) < 0)
  {
   perror("recv"); 
  }
 
 insert_USERList(USER,buff.users_sockaddr,buff.user_fd,"r");
 if(buff.user_fd==6000)break;//如果接收到这个标志位,就说明接收完毕
   }
  
   show_online_users_list(USER);//显示在线用户列表
 
    choosechatmode(sockfd,c);//群聊还是私聊模式选择
   
 /*发送消息给服务器端*/
  memset(&buff,0,sizeof(USER_List)); 
  if(strcmp(c,"sinp")==0)//如果选择单人聊天模式
 { 
  do
  {
      printf("Please input the user liner number!!\n");
   scanf("%d",&fd);
   buff.rece_id=fd;//就把选择目标ID存入。
  }while(chack_socket_number(USER,fd));//检查目标ID是否在上线用户列表中
 }
  strcpy(buff.buf,c);//把聊天模式选择标志位加入数组头
   

  printf("You can chat now!\n");

 
  /* 创建子进程 */
 if((child=fork())==-1)
 {
  printf("Fork Error \n");
  exit(1);
 }
    while(1)
   {
  if(child==0) // 子进程
  {
     scanf("%s",buff.buf+4);
     if(strncmp("sinp",buff.buf+4,4)==0)//如果切换到私聊模式
     {
         show_online_users_list(USER);//显示在线用户列表
               do
       {
                  printf("Please input the user liner number!!\n");
             scanf("%d",&fd);
             buff.rece_id=fd;//就把选择目标ID存入。
          }while(chack_socket_number(USER,fd));//检查目标ID是否在上线用户列表中
          strcpy(buff.buf,"sinp");//把聊天模式选择标志位加入数组头
     }
     else if(strncmp("manp",buff.buf+4,4)==0)
     {
          strcpy(buff.buf,"manp");//把聊天模式选择标志位加入数组头
     }
    
     if ((sendbytes = send(sockfd, &buff,sizeof(USER_List), 0)) == -1)
     {
      perror("send");
      exit(1);
     }
  }
  
  
  else if(child>0)//父进程
  {
   memset(&rebuff, 0, sizeof(USER_List));
   if (recv(sockfd, &rebuff,sizeof(USER_List), 0) > 0)
   {
    if(strcmp(rebuff.del,"del")==0)//判断是否有人离线
    {
                   printf("\33[33m\33[1m");
       printf("The %d is outline!!\n",rebuff.user_fd);
       printf("\33[0m\n");
       delet_List(USER,rebuff.user_fd);//将下线用户从用户列表中删除
    }

    if(strcmp(rebuff.del,"inl")==0)//判断是否有人上线
    {
                   printf("\33[33m\33[1m");
       printf("The %d is inline!!\n",rebuff.user_fd);
       printf("\33[0m\n");
       insert_USERList(USER,rebuff.users_sockaddr,rebuff.user_fd,"w");//将新上线用户追加到列表
    }
    else
    {
    printf("\33[33m\33[1m");
    printf("Received %d:%s\n",rebuff.rece_id,rebuff.buf+4);
    printf("\33[0m\n");
    }
   }
  }

   } 
 
close(sockfd);
exit(0);
}

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:183239次
    • 积分:2276
    • 等级:
    • 排名:第16449名
    • 原创:41篇
    • 转载:22篇
    • 译文:0篇
    • 评论:48条
    最新评论