- 论坛徽章:
- 0
|
回复 7# linux_c_py_php
大神,我简单写了一个,发现效率不够高啊。。帮我看看结构有问题不。。谢谢了。
代码如下:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "sys/epoll.h"
#include "fcntl.h"
#include "sys/ioctl.h"
#include "errno.h"
#include "pthread.h"
#include "sys/stat.h"
#include <sys/types.h>
#include <dirent.h>
#include "signal.h"
struct user_data{
int fd;
int head;
long length;
char filename[5000];
};
int setnonblocking(int sock)
{
int flag;
fcntl(sock,F_GETFL,&flag);
flag|=O_NONBLOCK;
if(fcntl(sock,F_SETFL,&flag)== -1)
{
int on=1;
if(ioctl(sock,FIONBIO,&on)==-1)
{
printf("SETFL ioctl error\n" ;
return 1;
}
}
return 0;
}
void main(int argc,char *argv[])
{
struct sigaction sa;
sa.sa_handler=SIG_IGN;
sigaction(SIGPIPE,&sa,0);
int len,nfds,opts,client_sockfd,listenfd;
struct sockaddr_in server_addr,client_addr;
listenfd=socket(AF_INET,SOCK_STREAM,0);
setnonblocking(listenfd);
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(atoi(argv[1]));
server_addr.sin_addr.s_addr=inet_addr("192.168.3.165" ;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,1,sizeof(int));
int nRecvBuf=32*1024;
setsockopt(listenfd,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
bind(listenfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
listen(listenfd,50);
fork();
fork();
int epfd=epoll_create(500);
struct epoll_event events[200];
struct epoll_event ev1;
ev1.data.fd=listenfd;
ev1.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev1);
int i;
for(;
{
nfds=epoll_wait(epfd,events,20,500);
for(i=0;i<nfds;i++)
{
if(events.data.fd== listenfd )
{
client_sockfd=accept(listenfd,NULL,NULL);
int re=setnonblocking(client_sockfd);
if(re == 1){close(client_sockfd);continue;}
ev1.data.fd=client_sockfd;
ev1.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,client_sockfd,&ev1);
}
else if(events.events&EPOLLIN)
{
client_sockfd=events.data.fd;
char last[5000]="",buf1[100];
int len=0;
int n,read_num;
ioctl(client_sockfd,FIONREAD,&read_num);
while(len < read_num)
{
if((n=read(client_sockfd,buf1,99))<0)
{
if(errno == ECONNRESET)
{
close(client_sockfd);
break;
}
else if(errno == EAGAIN){
break;
}
}
else if(n == 0)
{
break;
}
buf1[n]='\0';
len=len+n;
strcat(last,buf1);
}
char cmd[200],arg[2048];
strcpy(arg,"/tmp/taat" ;
sscanf(last,"%s%s",cmd,arg+9);
if(strcmp(arg,"/tmp/taat/" == 0)
strcpy(arg,"/tmp/taat/index.html" ;
if(strcmp(arg,"/tmp/taat" ==0)
strcpy(arg,"/tmp/taat/index.html" ;
struct user_data *new=(struct user_data *)malloc(sizeof(struct user_data));
new->fd=client_sockfd;
strcpy(new->filename,arg);
new->length=0;
new->head=0;
ev1.data.fd=client_sockfd;
ev1.data.ptr=new;
ev1.events=EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,client_sockfd,&ev1);
}
else if(events.events&EPOLLOUT)
{
struct user_data *old=(struct user_data *)events.data.ptr;
int fd=old->fd;
int len=old->length;
char filename[1000];
strcpy(filename,old->filename);
//-----------------------------------
FILE *file;
file=fopen(filename,"rb" ;
if(file == NULL)
{
printf("file %s open failed\n",filename);
ev1.data.fd=fd;
epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev1);close(fd);free(old);old=NULL;continue;
}
if(old->head == 0)
{
char type[100]="Content-Type: text/html";
char *ta;
ta=strrchr(filename,'.');
if(ta == NULL)
{
fclose(file);
printf("prefix %s get failed\n",filename);
ev1.data.fd=fd;
epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev1);close(fd);free(old);old=NULL;continue;
}
ta=ta+1;
if(strcmp(ta,"html" == 0)
strcpy(type,"Content-Type: text/html");
if(strcmp(ta,"txt") == 0)
strcpy(type,"Content-Type: text/plain");
if(strcmp(ta,"gif") == 0)
strcpy(type,"Content-Type: text/gif");
if(strcmp(ta,"jpg") == 0)
strcpy(type,"Content-Type: text/jpg");
if(strcmp(ta,"png") == 0)
strcpy(type,"Content-Type: text/png");
char content[200];
sprintf(content,"HTTP/1.1 200 OK\r\n%s\r\n\r\n",type);
if(write(fd,content,sizeof(char)*strlen(content))<0)
{
fclose(file);
printf("write content error\n");
ev1.data.fd=fd;epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev1);close(fd);free(old);old=NULL;continue;
}
old->head=1;
}
fseek(file,len,SEEK_SET);
int num;
char buf[5000];
while((num=fread(buf,sizeof(char),4999,file))>0)
{
buf[num]='\0';
int num1;
num1=write(fd,buf,num);
if (num1 < num)
{
if (num1 == -1 && errno != EAGAIN)
{ perror("write error"); }
break;
}
}
long curpos=ftell(file);
fseek(file, 0L, SEEK_END);
long all_len = ftell(file);
if(curpos == all_len)
{
printf("file %s read and send over\n",filename);
fclose(file);
ev1.data.fd=fd;epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev1);close(fd);free(old);old=NULL;continue;
}
else{
printf("file %s read and send not over\n",filename);
old->length=curpos;
fclose(file);
}
//-------------------------------------
}
}
}
}
而且我用ab测试的时候fcntl有很多失败呢。。求指导效率改进。
|
|