• 使用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; } } }

     

     

  • 相关阅读:
    网友谈:Dictionary.ContainsKey和List.BinarySearch哪个效率高
    C# WinForm 中在窗口标题栏上加按钮
    将Txt文件转换成dataset[原创]
    四个常见的排序算法[原创]
    改版后的groupbox[原创]
    转 五种提高 SQL 性能的方法
    转 牢记!SQL Server数据库开发的二十一条军规(SQL收藏)
    源码详解Java的反射机制
    java多线程采集+线程同步
    jQgrid API
  • 原文地址:https://www.cnblogs.com/defen/p/5287667.html
Copyright © 2020-2023  润新知