zoukankan      html  css  js  c++  java
  • linuxC网络聊天室简单代码,CSDN博客迁移

    学习总结:因为前一段对LINUX –C的学习也对网络编程有一点的认识,通过这一次聊天室的制作,更增加对学习新知识的兴趣。写聊天室时主要遇到的

    问题是

    1.服务器实现并发功能(接受和发送)

    2.实现多客户端连接服务器。

    3.怎样识别客户端之间的差别与联系

    4.实现多客户端之间的接受和发送。

    问题解决方案

    1.实现并发服务,我主要用了线程进行接收,通过接收的信息在识别创建发送线程。在服务器主函数中主要管理客户端的连接。

    2.在主函数中连接客户端主要是用数组贮存接收成功后(accept函数)的标识符,这样每个客户端都可连接,并且客户端可区分。

    3.我用接收成功后的标识符和客户端的用户名进行客户端识别。

    4.服务器通过客户端发送过来的字符串进行识别,发送的是个人还是群聊。

    这次写的比较简单,代码还可以进行完善和功能添加。

    服务器:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <string.h>
    #include <memory.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <error.h> 
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include<termios.h>
    
    #define MAX_LINE 1024
    #define MAX_CLIENT 15
    
    char recvbuf[MAX_LINE]={0};    //传送内容缓冲区
    int num=0;              //客户端连接标记
    char sendbuf[MAX_LINE]={0};
    int client[MAX_CLIENT];
    //FD_SETSIZE,1024是tcp最大连接数,client[FD_SETSIZE] 存放有数据请求的客户端;
    char name[15][1024]={0};
    
    int FLACE=0;
    
    int findname(char *name1)
    {
     int i = 0;
     for(i=0;i<5;i++)
     {
     printf("name[%d]=%s
    ",i,name[i]);
     }
     printf("find_name:%s",name1);
     for (i = 0; i < MAX_CLIENT; i++)
     {
        if (client[i]!=-1&&(strcmp((name[i]), name1))==0)     
            return i;
     } 
     return -1;
    }
    void sendto_one(int *client_num)
    {
            char buf[1024]={0};
            char recvname[20] = { 0 };
            char *p = strtok(sendbuf + 3, "
    ");//TO:3个字符后取出
    前的名字
            printf("(p)=%sa
    ",p);
            strcpy(recvname, p);
            int sock= findname(recvname);
            if(sock==0)
            {
            memset(buf, 0,MAX_LINE);
            sprintf(buf,"此人没上线
    ");
            send(client[*client_num],buf,strlen(buf),0);
            }
            printf("(sock=)%d
    ",sock);
            while(1)
            {
               if(sock!=-1&&num==1)
             {
               memset(buf, 0,MAX_LINE);
               sprintf(buf,"FPOM:%s
    %s",name[*client_num],sendbuf+4+strlen(p)+2);
               send(client[sock],buf,strlen(buf),0);
               printf("send success
    ");
               num=0;
             }
            }
    }
    void sendto_all(int *client_num)
    { 
     int i,j;
     char buf[1024] = { 0 };
     printf("send.buf=%s
    ",sendbuf);
     memset(buf, 0,MAX_LINE);
     sprintf(buf, "FPOM:%s
    %s",name[*client_num],sendbuf);
            j=0;
     printf("sendto_all11.buf=%s
    ",buf);
     for(i=0;i<15;i++)
     {
       printf("client[%d]=%d
    ",i,client[i]);
     }
     while(1)
     {
      while(j<10)
      {
        if(client[j]!=-1&&num==1) 
        {
          printf("name[j]%s",name[j]);
          send(client[j],buf,MAX_LINE,0);
        }
        printf("send to kehu
    ");
        j++;  
      }
      num=0;
     } 
    }
    void recvwhole(int* client_num)
    {
     int n;
     pthread_t tid2,tid3;
     while(1)
     {
        memset(recvbuf, 0,MAX_LINE);//初始化数组
        n=0;
        n=recv(client[*client_num],recvbuf,MAX_LINE,0);
        if(n>0)
        {
          printf("(recv.buf=)%s
    ",recvbuf);
          memset(sendbuf, 0,MAX_LINE);//初始化数组
          strcpy(sendbuf,recvbuf);
          num=1;
          printf("(num=)%d,
    (sendbuf:)
    %s
    ",num,sendbuf);
        }
        if (!strncmp(sendbuf, "TO:",3))
         {
                printf("发送个人
    ");
                pthread_create(&tid2,NULL,(void*)sendto_one,(void*)client_num);
                pthread_detach(tid2);           
         }
         if (!strncmp(sendbuf, "ALL
    ", 5))
         {
                printf("发送群体
    ");
                pthread_create(&tid3,NULL,(void*)sendto_all,(void*)client_num);
                pthread_detach(tid3);
         }
     }
    }
    
    int input_name(int *n)
    {
     int a,b;
     memset(sendbuf, 0,MAX_LINE);
     //sprintf(sendbuf,"请输入你的姓名:");
     //a=send(client[*n],sendbuf,MAX_LINE,0);
     b=recv(client[*n],name[*n],MAX_LINE,0);
     printf("(name[%d]=)%s
    ",*n,name[*n]);
     if(b>0)
     {return 0;}
     else
     {
       input_name(n);
     }  
    }
    
    
    void *pthread_fun(int * client_num)
    {
     if(input_name(client_num))
     {
       perror("input name fail");exit(-1);
     }
     char *p;
     pthread_t tid1,tid2,tid3;
     pthread_create(&tid1,NULL,(void*)recvwhole,/);
     pthread_detach(tid1);              
    }
    
    
    
    
    
    int main(int argc,char *argv[])
    {
     struct sockaddr_in addr;//保存客户端地址
     socklen_t len;         //保存客户端地址长度
     struct sockaddr_in add2;
     
     int port=8800;
     char addr_p[INET_ADDRSTRLEN];
     int i=0,ii;
     int lfd,cfd;               //套接字
     int a[15];
     
     pthread_t tid1,tid2; //创建线程变量
     
     bzero(&addr,sizeof(addr));//清空地址结构
     addr.sin_family=AF_INET;//使用IP4
     addr.sin_port=htons(port);//端口号
     addr.sin_addr.s_addr=INADDR_ANY;//服务器可以接受任意地址
     
      
     for(i=0;i<MAX_CLIENT;i++)
       {   client[i]=-1;}
     
    //1
     if((lfd=socket(AF_INET,SOCK_STREAM,0))==-1)
     {
       perror("fail to socket");exit(1);
     }
     printf("创建套接字成功
    ");
     
     //设置端口可重用
     int opt = 1;
     setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  //将套接字绑定到服务器的网络地址上
     
     
     //2
     if(bind(lfd,(struct sockaddr*)&addr,sizeof(addr))==-1)
     {
     perror("fial to bind");exit(1);
     }
     printf("绑定地址套接字成功
    ");
    //3
     if (listen(lfd, 10) == -1)
     {  
        perror("fail to listen"); exit(1);
     }
     printf("监听成功
    ");
     
     i=0;
     while(i<MAX_CLIENT)  
     {
      ii=i;
      len=sizeof(add2);
      client[i]=accept(lfd,(struct sockaddr*)&add2,&len);
      //printf("
    **%d
    ",client[i]);  
      printf("接受成功,i = %d
    ",i);
      
      
      printf("create thread
    ");
      a[i]=i; 
      if(pthread_create(&tid1,NULL,(void*)pthread_fun,&a[i])!=0)
      {
        perror("create success");exit(-1);
      }
      pthread_detach(tid1);
      i++;  
      if(ii<i)
      {
        inet_ntop(AF_INET,&addr.sin_addr,addr_p,sizeof(addr_p));////将客户端地址转换为字符串
        printf("IP=%s,port=%d
    ",addr_p,ntohs(addr.sin_port)); 
      } 
    客户端:
    
    #include<stdio.h>
    #include<unistd.h>
    #include<string.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    
    #define MAX_LINE 1024
    
    char buf[MAX_LINE];
    int port=8800;
    char name[200]={0};
    int FLACE=0;
    
    void fun_all(int sockfd)
    {
     char sendbuf[1024]={0};
     sprintf(sendbuf,"ALL
    ",5);
     printf("
    ");getchar();
     printf("输入聊天内容:
    ");
     fgets(sendbuf+strlen(sendbuf),100,stdin);
     //scanf("%s",sendbuf+5);
     //sprintf(sendbuf+strlen(sendbuf),"
    ");
     printf("(all      sendbuf)=%s
    ",sendbuf);
     if(send(sockfd,sendbuf,strlen(sendbuf),0)<=0)
     {
     printf("send error
    ");close(sockfd);exit(1);
     }
    }
    void fun_one(int sockfd)
    { 
     char sendbuf[1024] = {0};
     char name3[20] ;
     printf("输入聊天对象:");getchar();
     memset(name3,0,20);
     fgets(name3,20,stdin);
       printf("(name3)
    %s",name3);
       sprintf(sendbuf,"TO:%s
    ",name3); 
     printf("输入聊天内容:
    ");
     fgets(sendbuf+strlen(sendbuf),100,stdin);
     //printf("(sendbuf)=%s
    ",sendbuf);
     //sprintf(sendbuf+strlen(sendbuf),"
    "); 
     if(send(sockfd,sendbuf,strlen(sendbuf),0) <= 0)
     {    
     printf("send err
    ");  
     close(sockfd);
        exit(1);
     }
     
    }  
    void menu()
    {
     printf("^^^^^^^^^^^^^^^^^^^^
    ");
     printf("1.私聊模式(发送to)
    ");
     printf("2.群聊模式(发送all)
    ");
     printf("~~~~~~~~~~~~~~~~~~~~
    ");
    }
    
    void *fun(int *sock)
    {
     int sockfd=*sock;
     int n;
     char *p,*q;
     char name2[20]={0};
     
     while(1)
     { n=0;
      memset(buf,0,MAX_LINE);//初始化数组
      n=recv(sockfd,buf,MAX_LINE,0);
      if(n>0)
      {
      printf("
    
    接受到:");
      printf("
    *************
    %s******************
    ",buf);
      }  
      if(n<=0)
      {   
      printf("recv failed
    ");   
      exit(1);
      }
     }
    
    }
    
    
    
    int main(int argc,char *argv[])
    {
     int l_fd;//套接字
     struct sockaddr_in addr;
     char sendbuf[1024] = {0};
     char str[6] = {0};
     
     int n;
     pthread_t pid1; 
     bzero(&addr,sizeof(addr));
     addr.sin_family=AF_INET;
     inet_pton(AF_INET,"10.25.100.*",&addr.sin_addr);
     addr.sin_port=htons(port);
     
     if((l_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
     {
       perror("fail to creat socket");exit(1);
     }
     printf("创建套接字成功
    ");
     if(connect(l_fd,(struct sockaddr *)&addr,sizeof(addr)) == -1)
     {
       perror("fail to connect");exit(1);
     }
     printf("connect success
    ");
     
     memset(name,0,20);    
     printf("请输入你的姓名:");    
     scanf("%s",name);
     sprintf(sendbuf,name); //把格式化的数据写入某个字符串,"LOGIN
    %s
    
    "
     send(l_fd,sendbuf,strlen(sendbuf),0);
     //printf("sendbuf=%s
    ",sendbuf);
     
     pthread_create(&pid1,NULL,(void*)fun,(void*)&l_fd);
     pthread_detach(pid1);
     
     while(1)
     {
        menu();
        memset(str,0,6);      
        scanf("%s",str);
        if(!strcmp(str,"all"))
        {
            printf("群聊模式
    ");       
          fun_all(l_fd);       
          continue;      
        }       
        else if(!strcmp(str,"to"))
        {       
          printf("私聊模式
    ");       
          fun_one(l_fd);       
          continue;      
        }  
        else
          printf("请重新输入:");
     
      }
      wait(NULL);
      close(l_fd);
       return 0;
     }
       
     } 
      
     return 0;
    }  
  • 相关阅读:
    Python并行编程(七):线程同步之事件
    Python并行编程(六):线程同步之条件
    Python并行编程(五):线程同步之信号量
    Python并行编程(四):线程同步之RLock
    Python并行编程(三):线程同步之Lock
    UML关系总结——画uml图、流程图、软件结构图、类图、顺序图的方法
    2020,你好!
    字符串和多维数组
    排序算法
    查找技术
  • 原文地址:https://www.cnblogs.com/Lijcyy/p/13836901.html
Copyright © 2011-2022 走看看