使用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!\n");
    
    if(listen(socketfd,5)<0)
        perror("listen() error!\n");
    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("--------------\n");        
            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!\n");
            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\n",namebuf);        
                for(i=0;i<12;i++)
                {
                    if(fds[i].cfd==0)
                    {
                        fds[i].cfd = newsocketfd;
                        strcpy(fds[i].cname,namebuf);
                        printf("%s\n",fds[i].cname);    
//        printf("--------------\n");        
                        break;
                    }
                }
                    
            }
            continue;
            }
//            printf("helo\n");
/*将接受到的数据进行解析*/
            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!\n");
                        close(fds[i].cfd);
                    //    printf("core error!\n");
                        fds[i].cfd = 0;
                    //    printf("core error!\n");
                        break;
                    }
            //        printf("%s\n",buf1);
                    token = strtok(buf1,split);
            //        printf("token=%s\n",token);
                    tokem = strtok(NULL,split);
            //        printf("tokem=%s\n",tokem);
                    tokeu = strtok(NULL,split);
            //        printf("tokeu=%s\n",tokeu);

            /*判断是要给那个newsocketfd发送数据,然后将数据发送出去*/
                    for(i=0;i<12;i++)
                    {
                //        int flag;
                    //    printf("----\n");
                        if(!strncmp(fds[i].cname,token,3))
                        {    
                    //    printf("----\n");
                        strcat(tokeu,":");
                    //    printf("----\n");
                        strcat(tokeu,tokem);
                        printf("cname = %s\n",fds[i].cname);
                    
                    //    break;
                    
                        if(send(fds[i].cfd,tokeu,strlen(tokeu),0)<0)
                            perror("send() error!\n");
                    //    break;
                        }    
                        else
                        {
                        //    printf("this is not present!\n");
                        }
                    
                    }    
                }
                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!\n");
//只要与服务器连上立马将自己的昵称发送过去
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!\n"); printf("%s\n",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!\n"); continue; } } }

 

 

 

posted @ 2016-03-17 15:40  高傲的monkey  阅读(6791)  评论(0编辑  收藏  举报