select机制

来源:互联网 发布:淘宝上开网店步骤 编辑:程序博客网 时间:2024/05/16 14:51

server

/*************************************************************************    > File Name: server.cpp    > Author:     > Mail:     > Created Time: 2017年06月13日 星期二 20时12分15秒 ************************************************************************/#include<iostream>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<strings.h>#include<sys/wait.h>#include<string.h>#include<errno.h>#define DEFAULT_PORT 6666using namespace std;int main(int argc,char **argv){    int serverfd,acceptfd;    struct sockaddr_in my_addr;//服务器地址    struct sockaddr_in their_addr;//客户端的地址    unsigned int sin_size;    unsigned int myport=6666;    unsigned int lisnum=10;//一次监听的数目    if((serverfd=socket(AF_INET,SOCK_STREAM,0))==-1){        perror("socket error!\n");        return -1;    }    printf("socket ok\n");    my_addr.sin_family=AF_INET;//指明IPV4    my_addr.sin_port=htons(DEFAULT_PORT);    my_addr.sin_addr.s_addr=INADDR_ANY;//指明服务器地址为任意地址,一般默认网卡地址    bzero(&(my_addr.sin_zero),0);//指明某个变量的前多少个字节为0,这个很奇怪?    //解决套接字端    //口号不能立即释放问题,是由于TCP套接字的TIME_WAIT状态引起的int val=1;int ret1=setsockopt(serverfd,SOL_SOCKET,SO_REUSEADDR,(void*)&val,sizeof(int));    if(ret1==-1){        perror("setsockopt error\n");        exit(1);    }    if(bind(serverfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))==-1){        perror("bind error\n");        return -2;    }    printf("bind ok\n");    if(listen(serverfd,lisnum)==-1){        perror("listen");        return -3;    }    printf("listen ok\n");    fd_set client_fdset;//监听的文件描述符集合    int maxsock;//监听的文件描述符最大值,其实就是最大文件号    struct timeval tv;//超时返回时间    int client_sockfd[5];//存放活动的sockfd    bzero((void *)client_sockfd,sizeof(client_sockfd));    int conn_amount=0;//用来记录文件描述符数量    maxsock=serverfd;    char buffer[1024];    int ret=0;    while(1)    {        //初始化文件描述符集合        FD_ZERO(&client_fdset);        FD_SET(serverfd,&client_fdset);//把服务器描述符加入描述符集合        tv.tv_sec=30;        tv.tv_usec=0;//设置超时时间        for(int i=0;i<5;i++)        {            if(client_sockfd[i]!=0)                FD_SET(client_sockfd[i],&client_fdset);//把活跃的句柄加入到文件描述中        }        printf("put sockfd in fdset \n");        ret=select(maxsock+1,&client_fdset,NULL,NULL,&tv);        if(ret<0){            perror("select error \n");            break;        }        else if(ret==0)        {            printf("time out\n");            continue;        }        else        {            int clientsnum=conn_amount;            for(int i=0;i<clientsnum;i++)//轮询各个文件描述符            {                if(FD_ISSET(client_sockfd[i],&client_fdset))//                {                    printf("start recv from client[%d]:\n",i);                    ret=recv(client_sockfd[i],buffer,1024,0);                    if(ret<=0){                        printf("client[%d] close\n",i);//这里需要修改,关闭连接时,对应的conn_amount也应该减少,一会测试一下                        close(client_sockfd[i]);                        FD_CLR(client_sockfd[i],&client_fdset);                        client_sockfd[i]=0;                        conn_amount--;                    }                    else                        printf("recv from client[%d]:%s\n",i,buffer);                }            }        }        if(FD_ISSET(serverfd,&client_fdset)){//有新的连接,接收连接            struct sockaddr_in client_addr;            size_t size=sizeof(struct sockaddr_in);            int sock_client=accept(serverfd,(struct sockaddr*)(&client_addr),(unsigned int *)(&size));//返回客户端的fd            if(sock_client<0){                perror("accept error\n");                continue;            }            if(conn_amount<5)            {                 client_sockfd[conn_amount++]=sock_client;                bzero(buffer,1024);                strcpy(buffer,"This is server! Welcome!\n");                send(sock_client,buffer,1024,0);                printf("new connection client[%d] %s:%d\n",conn_amount,inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));                bzero(buffer,sizeof(buffer));                ret=recv(sock_client,buffer,1024,0);                if(ret<0){                    perror("recv error!\n");                    close(serverfd);                    return -1;                }                 printf("recv: %s\n",buffer);                if(sock_client>maxsock)                    maxsock=sock_client;            }            else            {                printf("max connections!!quit!\n");                break;            }        }    }    for(int i=0;i<5;i++)    {        if(client_sockfd[i]!=0)            close(client_sockfd[i]);    }    close(serverfd);    return 0;}

client

/*************************************************************************    > File Name: client.cpp    > Author:     > Mail:     > Created Time: 2017年06月13日 星期二 21时24分46秒 ************************************************************************/#include<iostream>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<strings.h>#include<sys/wait.h>#include<string.h>#include<errno.h>#define DEFAULT_PORT 6666using namespace std;int main(int argc,char **argv){    int connfd=0;    int cLen=0;    struct sockaddr_in client;    if(argc<2){        printf("Usage: client [server IP address]\n");        return -1;    }    client.sin_family=AF_INET;    client.sin_port=htons(DEFAULT_PORT);    client.sin_addr.s_addr=inet_addr(argv[1]);    connfd=socket(AF_INET,SOCK_STREAM,0);    if(connfd<0)    {        perror("socket error\n");        return -1;    }    if(connect(connfd,(struct sockaddr*)&client,sizeof(client))<0)    {        perror("connect");        return -1;    }    char buffer[1024];    bzero(buffer,sizeof(buffer));    recv(connfd,buffer,1024,0);    printf("recv: %s\n",buffer);    bzero(buffer,sizeof(buffer));    strcpy(buffer,"This is client\n ");    send(connfd,buffer,1024,0);    while(1)    {        bzero(buffer,sizeof(buffer));        //scanf("%s",buffer);        cin.getline(buffer,sizeof(buffer));         int p=strlen(buffer);        printf("buffer is %s\n Len is %d \n",buffer,p);        buffer[p]='\0';        send(connfd,buffer,1024,0);        printf("i have send buffer\n");    }    close(connfd);    return 0;}

makefile

all:server clientserver:server.o    g++ -g -o server server.oclient:client.o    g++ -g -o client client.oserver.o: server.cpp    g++ -g -c server.cppclient.o: client.cpp    g++ -g -c client.cppclear:all    rm all

解决bind错误 bind: Address already in use

http://www.cnblogs.com/Bro-Young/p/5762737.html
(优秀博客,推荐阅读)