unix 网络编程--select (一)

下面是一个很不错的select的例子,避免了调用fork而产生的新进程的开销:

下面是server 代码:

#include <stdio.h>
 #include <stdlib.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAXLINE  1024
typedef struct sockaddr_in sockaddr_in ;
typedef struct sockaddr sockaddr ;
#define MAX_FD_CONN		1000

int main(int argc ,char ** argv){

	int sock ,con;
	int nready ,nfd;
	sockaddr_in srv,cli ;

	if((sock=socket(AF_INET ,SOCK_STREAM,0))==-1){
		perror("socket ");
		return -1 ;
	}

	bzero(&srv,0);
	srv.sin_family = AF_INET ;
	srv.sin_port = htons(8070);
	srv.sin_addr.s_addr = htonl (INADDR_ANY) ;

	if((bind(sock,(sockaddr*)&srv,sizeof(sockaddr)))< 0){
		perror("bind");
		return -1 ;
	}
	listen(sock,10);
	char buf[1024];
	fd_set rset,allfd ;
	int conns[ MAX_FD_CONN ] ,i ,nr;
	socklen_t len ;
	for(i =0 ;i<MAX_FD_CONN;i++)
		conns[i] = -1;

	FD_ZERO(&allfd);
	FD_SET(sock,&allfd );
	nfd = sock+1;
	FD_SET(sock,&allfd);
	while(1){
		rset=allfd; //这个是相当的关键一行哦,UNP(1)上说,select 对参数是有修改的,一定要注意保存啊,不然会出现意想不到的问题

		nready = select(nfd, &rset,NULL,NULL,NULL );
		if (FD_ISSET(sock,&rset)) {
			len = sizeof(sockaddr);
			if ((con = accept(sock, (sockaddr*) &cli, &len)) == -1) {
				perror("accept");
				continue;
			}
			for(i =0 ;i<MAX_FD_CONN;i++){ /*if maxsize >MAX_FD_CONN, throw and close the connect */
				if(conns[i ] == -1){
					conns[i] = con;
					FD_SET(con,&allfd);
					break;
				}
			}
			if(MAX_FD_CONN == i)
				close(con);
			if(nfd <= con)
				nfd = con +1;

			if(--nready <= 0){
				continue ;
			}
		}


		for(i =0 ;i<MAX_FD_CONN;i++){
			if(conns[i]== -1)
				continue ;
			if(FD_ISSET(conns[i], &rset)){
				bzero(buf,sizeof(buf));
				if((nr=read(conns[i],buf,sizeof(buf)))<=0){
					close(conns[i]);
					FD_CLR(conns[i],&allfd);
					continue ;
				}else{
					printf("read:%s\n",buf);
					write(conns[i],buf, nr);
				}
			}
			if(--nready <= 0)
				break;
		}
	}
	close(sock);

	return 0;
}

在此我也把客户端连接的测试的代码也贴出来,分享一下,也防止以后忘了呵呵呵

#include <stdio.h>
 #include <stdlib.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAXLINE  1024
typedef struct sockaddr_in sockaddr_in ;
typedef struct sockaddr sockaddr ;


int main(int argc ,char ** argv){

	int sock ;
	int sel ,nfd;
	sockaddr_in srv,cli ;

	if((sock=socket(AF_INET ,SOCK_STREAM,0))==-1){
		perror("socket ");
		return -1 ;
	}

	bzero(&srv,0);
	srv.sin_family = AF_INET ;
	srv.sin_port = htons(atoi(argv[2]));
	inet_pton(AF_INET,argv[1],&srv.sin_addr);

	char buf[1024];
	fd_set rset ,wset;
	FD_ZERO(&rset);
	FD_ZERO(&wset);
	FD_SET(STDIN_FILENO ,&rset );
	FD_SET(sock ,&rset );
	if(connect(sock,(sockaddr*)&srv, sizeof(sockaddr))<0){
		perror("connect:");
		return -1 ;
	}
	perror("con");
	
	nfd = sock+1;
	int rn ;
	bzero(buf,sizeof(buf));
	while((sel = select(nfd, &rset,&wset,NULL,NULL ))){
		printf("select begin\n");

		if(FD_ISSET(sock,&rset)){
			bzero(buf,sizeof(buf));
			read(sock,buf,sizeof(buf));
			printf("read:%s\n",buf);
		}
		if(FD_ISSET(STDIN_FILENO,&rset)){
			bzero(buf,sizeof(buf));
			rn = read(STDIN_FILENO, buf,sizeof(buf));
			if(rn>0)
				FD_SET(sock,&wset );
		}
		if(FD_ISSET(sock, &wset)){
			int wn = write(sock,buf,rn );
			bzero(buf,sizeof(buf));
			FD_CLR(sock,&wset );
		}


		FD_SET(STDIN_FILENO ,&rset );
		FD_SET(sock ,&rset );
	}
	close(sock);


	return 0;
}
下面给出一个性能测试实例
下面使用200个线程,而且是并发执行哦!每个线程写入1000*1000*10B的数据
测试成功
typedef struct sockaddr_in      sockaddr_in;
typedef struct sockaddr         sockaddr ;

void *thread_fun(void*arg ){
    
        struct sockaddr_in ser,cli ;
        int fd ,bs,fdc,i;
        socklen_t len;
        char buf[1024];

        bzero(&ser,sizeof(sockaddr));
        ser.sin_port = 8080;
        inet_pton(AF_INET,"10.33.28.230",(void*)&ser.sin_addr);
        ser.sin_family = AF_INET ;
        fd = socket(AF_INET,SOCK_STREAM, 0); 
        if(fd<0)
                perror("socket error\n");
        //int nZero=0;
        //setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));
        printf("threadID:%d\n",(int)arg);
        sleep(2);
        connect(fd,(sockaddr*)&ser,sizeof(sockaddr));
        for(i=0;i<1000*1000;i++){
                bzero(buf,sizeof(buf));
                sprintf(buf,"%10d",(int)arg);
                if(write(fd,buf,strlen(buf))<=0)
                        perror("write error:");
        }   
//      printf("%d\n",i);
        close(fd);
//      sleep(1);
        pthread_exit((void*)arg);
}
const int num_thre = 200;
int main(){
        int i =0;
        int res;
       pthread_t send_msg[num_thre];
        for(i=0;i<num_thre;i++){
                if(pthread_create(send_msg+i,NULL,thread_fun,i)!=0)
                        printf("pthread create error\n");
        }

        for(i=0;i<num_thre;i++){
                pthread_join(send_msg[i],(void**)(&res));
                printf("%dover\n",res);
        }
        printf("over \n");
        return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值