zoukankan      html  css  js  c++  java
  • 使用tcp+select实现客户端与客户端的通信

    使用多路复用实现客户端与客户端进行通信;

    原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将newsocketfd存放在同一个结构体中,客户端先给服务器发送数据,然后通过服务器转发给客户端。(服务器先会查找对应名字的newsocketfd 然后向该newsocketfd中写入数据)。

     

    服务器端程序:
    #include<stdio.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include<pthread.h>
    #include<strings.h>
    struct fd_info
    {
        int cfd;
        char cname[120];
    };
    void send1(struct fd_info a[])
    {
        int i;
        char buf[50];
        bzero(buf,50);
        fgets(buf,50,stdin);
        for(i=0;i<12;i++)
        {    if(a[i].cfd !=0)
            send(a[i].cfd,buf,50,0);
        }
    }
    int main()
    {
        struct fd_info fds[12]; 
        
        int maxfd = -1;
        
        int socketfd = socket(PF_INET,SOCK_STREAM,0);
        if(socketfd>maxfd)
            maxfd = socketfd;
        struct sockaddr_in saddr;
        memset(&saddr,0,sizeof(saddr));
        saddr.sin_family = PF_INET;
        saddr.sin_port = htons(6000);
        saddr.sin_addr.s_addr = inet_addr("192.168.1.46");
        int newsocketfd;
        int n = 1;
        setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int));
        if(bind(socketfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<0)
            perror("bind() error!
    ");
        
        if(listen(socketfd,5)<0)
            perror("listen() error!
    ");
        struct sockaddr_in caddr;
        int s = sizeof(struct sockaddr);
    //    newsocketfd = accept(socketfd,(struct sockaddr*)&caddr,&s);
        fd_set fd;
        FD_ZERO(&fd);
        int ret;
        char buf[50],buf1[50];
        int i;
        for(i=0;i<12;i++)
        {
            fds[i].cfd = 0;    
        }
        char namebuf[120];
        int rsize;
        char *split = ":";
        char *token,*tokem,*tokeu;
        while(1)
        {    
            FD_ZERO(&fd);
            FD_SET(0,&fd);    
            FD_SET(socketfd,&fd);
    /*将新socket加入到fd_set中*/
            for(i=0;i<12;i++)
            {
    //        printf("--------------
    ");        
                if(fds[i].cfd!=0)
                FD_SET(fds[i].cfd,&fd);
            }
    /*监视老socketfd的状态是否改变,一旦改变说明有新的服务器连接进来
    然后接受客户端发送过来的数据,并将其和newsocketfd存放于同一个结构体中*/
            ret = select(maxfd+1,&fd,NULL,NULL,NULL);
            if(ret<0)
            {
                perror("select() error!
    ");
                break;
            }
            else if(ret ==0)
            {
                continue;
            }
            else
            {
                if(FD_ISSET(socketfd,&fd))
                {
                    newsocketfd = accept(socketfd,(struct sockaddr*)&caddr,&s);
                if(newsocketfd>maxfd)            
                {        
                    maxfd = newsocketfd;
                
                recv(newsocketfd,namebuf,120,0);
                    
        //    printf("%s
    ",namebuf);        
                    for(i=0;i<12;i++)
                    {
                        if(fds[i].cfd==0)
                        {
                            fds[i].cfd = newsocketfd;
                            strcpy(fds[i].cname,namebuf);
                            printf("%s
    ",fds[i].cname);    
    //        printf("--------------
    ");        
                            break;
                        }
                    }
                        
                }
                continue;
                }
    //            printf("helo
    ");
    /*将接受到的数据进行解析*/
                for(i=0;i<12;i++)
                {
                    if((fds[i].cfd !=0) && FD_ISSET(fds[i].cfd,&fd))
                    {
                        bzero(buf1,50);
                        if(recv(fds[i].cfd,buf1,50,0)==0)
                        {
                            //printf("core error!
    ");
                            close(fds[i].cfd);
                        //    printf("core error!
    ");
                            fds[i].cfd = 0;
                        //    printf("core error!
    ");
                            break;
                        }
                //        printf("%s
    ",buf1);
                        token = strtok(buf1,split);
                //        printf("token=%s
    ",token);
                        tokem = strtok(NULL,split);
                //        printf("tokem=%s
    ",tokem);
                        tokeu = strtok(NULL,split);
                //        printf("tokeu=%s
    ",tokeu);
    
                /*判断是要给那个newsocketfd发送数据,然后将数据发送出去*/
                        for(i=0;i<12;i++)
                        {
                    //        int flag;
                        //    printf("----
    ");
                            if(!strncmp(fds[i].cname,token,3))
                            {    
                        //    printf("----
    ");
                            strcat(tokeu,":");
                        //    printf("----
    ");
                            strcat(tokeu,tokem);
                            printf("cname = %s
    ",fds[i].cname);
                        
                        //    break;
                        
                            if(send(fds[i].cfd,tokeu,strlen(tokeu),0)<0)
                                perror("send() error!
    ");
                        //    break;
                            }    
                            else
                            {
                            //    printf("this is not present!
    ");
                            }
                        
                        }    
                    }
                    continue;    
                }
                /**给所有客户端发送数据*/
                    if(FD_ISSET(0,&fd))
                    {
                        send1(fds);
                    }
        }
        }
        close(socketfd);
        close(newsocketfd);
    
    }
    
     //客户端代码:
    #include<stdio.h>
    #include<pthread.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    #include<string.h>
    #include<strings.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    int main(int argc,char **argv)
    {
        int socketfd,ret;
        fd_set fd;
        FD_ZERO(&fd);
        FD_SET(0,&fd);
            
        
        socketfd = socket(PF_INET,SOCK_STREAM,0);
        FD_SET(socketfd,&fd);
        ret = select(socketfd+1,&fd,NULL,NULL,NULL);
        struct sockaddr_in saddr;
        memset(&saddr,0,sizeof(saddr));
        saddr.sin_family = PF_INET;
        saddr.sin_port = htons(6000);
        saddr.sin_addr.s_addr = inet_addr("192.168.1.46");
        
        if(connect(socketfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr))<0)
    
            perror("connect() error!
    ");
    //只要与服务器连上立马将自己的昵称发送过去
    send(socketfd,argv[0],strlen(argv[0]),0); char buf[50],buf1[50]; while(1) { bzero(buf,50); bzero(buf1,50); FD_SET(0,&fd); FD_SET(socketfd,&fd); ret = select(socketfd+1,&fd,NULL,NULL,NULL); if(FD_ISSET(socketfd,&fd)) { if(recv(socketfd,buf1,sizeof(buf1),0)<0) perror("recv() error! "); printf("%s ",buf1); continue; } if(FD_ISSET(0,&fd)) { scanf("%s",buf); strcat(buf,":"); strcat(buf,argv[0]); if(send(socketfd,buf,strlen(buf),0)<0) perror("send() error! "); continue; } } }

     

     

  • 相关阅读:
    atitit.TokenService v3 qb1 token服务模块的设计 新特性.docx
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    atitit。企业的价值观 员工第一 vs 客户第一.docx
    Atitit 实现java的linq 以及与stream api的比较
    Atitit dsl exer v3 qb3 新特性
    Atititi tesseract使用总结
    Atitit 修改密码的功能流程设计 attilax总结
    atitit.TokenService v3 qb1  token服务模块的设计 新特性.docx
  • 原文地址:https://www.cnblogs.com/defen/p/5287667.html
Copyright © 2011-2022 走看看