下面是一个很不错的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; }