- 论坛徽章:
- 0
|
本帖最后由 hegu 于 2011-05-31 11:53 编辑
我的代码就是一个简单的http server,对任何请求都是返回200 OK。
我的测试方法就是用curl一个url。
这个是我的一个log,可以看到经常收到连接后,9秒才收到数据,感觉应该不是网络原因,
因为我curl服务器的nginx的一个文件,响应就很快。
current_conn=441 123.125.117.250-242 r-c=3 r=0 w-r=0 w=0 spend=3
Mon May 30 16:24:41 2011 connect
Mon May 30 16:24:41 2011 rec 403
Mon May 30 16:24:41 2011 writed 89
current_conn=1866 123.125.117.250-39618 r-c=0 r=0 w-r=0 w=0 spend=0
Mon May 30 16:24:42 2011 connect
Mon May 30 16:24:42 2011 rec 403
Mon May 30 16:24:42 2011 writed 89
current_conn=1782 123.125.117.250-228 r-c=0 r=0 w-r=0 w=0 spend=0
Mon May 30 16:24:43 2011 connect
Mon May 30 16:24:43 2011 rec 403
Mon May 30 16:24:43 2011 writed 89
current_conn=1820 123.125.117.250-2331 r-c=0 r=0 w-r=0 w=0 spend=0
Mon May 30 16:24:44 2011 connect
Mon May 30 16:24:47 2011 rec 403
Mon May 30 16:24:47 2011 writed 89
current_conn=1879 123.125.117.250-14107 r-c=3 r=0 w-r=0 w=0 spend=3
Mon May 30 16:25:08 2011 connect
Mon May 30 16:25:17 2011 rec 403
Mon May 30 16:25:17 2011 writed 89
current_conn=1842 123.125.117.250-22503 r-c=9 r=0 w-r=0 w=0 spend=9
下面是我的代码:
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <sstream>
using namespace std;
#define LISTENQ 20000
#define SERV_PORT 9889
#define HTTP_END "\r\n\r\n"
//#define HTTP_END "abcd"
#define HTTP_200_OK "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: no-cache\r\nContent-Length: 0\r\n\r\n"
//#define HTTP_200_OK "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: no-cache\r\nContent-Length: "
#define TEST_IP "123.125.117.250"
int CreateWorker(int nWorker)
{
if (0 < nWorker)
{
bool bIsChild = false;
pid_t nPid;
while (!bIsChild)
{
if (0 < nWorker)
{
nPid = ::fork();
if (nPid > 0)
{
bIsChild = false;
--nWorker;
}
else if (0 == nPid)
{
bIsChild = true;
printf("create worker %d success!\n", ::getpid());
}
else
{
printf("fork error: %s\n", ::strerror(errno));
return -1;
}
}
else
{
int nStatus;
if (-1 == ::wait(&nStatus))
{
}
printf("wait status=%d\n", nStatus);
++nWorker;
}
}
}
return 0;
}
void setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
class http_task
{
public:
int fd;
struct sockaddr_in remoteAddr;
char recv_buffer[1024];
int recved;
int Writed;
static int current_connect;
string strInfoHash;
unsigned int connect_time;
unsigned int read_begin_time;
unsigned int read_end_time;
unsigned int write_begin_time;
unsigned int write_end_time;
http_task():fd(0),Writed(0),read_begin_time(0),read_end_time(0),write_begin_time(0),write_end_time(0),recved(0)
{
current_connect++;
connect_time = time(NULL);
};
~http_task()
{
current_connect--;
};
};
int http_task::current_connect = 0;
void delete_http_task(int epfd,http_task* ptask)
{
int sockfd = ptask->fd;
if (strcmp(inet_ntoa(ptask->remoteAddr.sin_addr),TEST_IP) == 0)
{
time_t tNow = time( NULL );
// char *szTime = asctime( localtime( &tNow ) );
// szTime[strlen( szTime ) - 1] = '\0';
ptask->write_end_time = time(NULL);
int spend = time(NULL)-ptask->connect_time;
stringstream ss;
ss << "current_conn="<<ptask->current_connect << " "
<< inet_ntoa(ptask->remoteAddr.sin_addr) << "-" << ptask->remoteAddr.sin_port << " "
<< "r-c=" << ptask->read_begin_time-ptask->connect_time << " "
<< "r=" << ptask->read_end_time-ptask->read_begin_time << " "
<< "w-r=" << ptask->write_begin_time-ptask->read_end_time << " "
<< "w=" << ptask->write_end_time-ptask->write_begin_time << " "
<< "spend=" << spend;
std::cout << ss.str() << endl;
}
delete ptask;
epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);
close(sockfd);
};
int main()
{
int i, listenfd, connfd, sockfd,epfd,nfds;
ssize_t n;
socklen_t clilen;
const int MAX_EVENT = 20;
struct epoll_event ev,events[MAX_EVENT];
struct sockaddr_in clientaddr;
struct sockaddr_in serveraddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_port=htons(SERV_PORT);
int nOptVal = 1;
socklen_t nOptLen = sizeof(int);
if (-1 == ::setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &nOptVal, nOptLen))
{
return -1;
}
setnonblocking(listenfd);
bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
listen(listenfd, LISTENQ);
CreateWorker(5);
epfd = epoll_create(25600);
ev.data.fd=listenfd;
ev.events=EPOLLIN|EPOLLET;
//ev.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
struct sockaddr_in remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
http_task *ptask;
while(true)
{
nfds=epoll_wait(epfd,events,MAX_EVENT,-1);
for(i=0;i<nfds;++i)
{
if(events.data.fd==listenfd && (events.events&EPOLLIN))
{
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)&remoteAddr, &remoteAddrLen);
if(connfd == -1)
{
if(errno == EWOULDBLOCK || errno == EAGAIN)
{
//printf("none connections\n");
break;
}
perror("accept error");
return -1;
}
//printf("%d: %s coming\n",getpid(),inet_ntoa(remoteAddr.sin_addr));
setnonblocking(connfd);
ptask = new http_task;
ptask->fd = connfd;
ptask->remoteAddr = remoteAddr;
ev.data.ptr = ptask;
ev.events=EPOLLIN|EPOLLET;
//ev.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
if (strcmp(inet_ntoa(ptask->remoteAddr.sin_addr),TEST_IP) == 0)
{
time_t tNow = time( NULL );
char *szTime = asctime( localtime( &tNow ) );
szTime[strlen( szTime ) - 1] = '\0';
std::cout<< szTime <<" connect "<<std::endl;
}
}
}
else if(events.events&EPOLLIN)
{
ptask = (http_task*)events.data.ptr;
sockfd = ptask->fd;
int nRecv;
if (ptask->read_begin_time == 0)
{
ptask->read_begin_time = time(NULL);
}
//do
//{
nRecv = read(sockfd, ptask->recv_buffer+ptask->recved, 1024-ptask->recved);
if (strcmp(inet_ntoa(ptask->remoteAddr.sin_addr),TEST_IP) == 0)
{
time_t tNow = time( NULL );
char *szTime = asctime( localtime( &tNow ) );
szTime[strlen( szTime ) - 1] = '\0';
std::cout<< szTime <<" rec " << nRecv <<std::endl;
}
//}while(nRecv == 1024);
if (nRecv < 0)
{
if (errno == ECONNRESET)
{
}
else
{
std::cout<<"readline error"<<std::endl;
}
delete ptask;
epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,&ev);
close(sockfd);
}
else
{
ptask->recved += nRecv;
if (ptask->recved > 4 && memcmp(&ptask->recv_buffer[ptask->recved-4],HTTP_END,4) == 0)
{
ptask->read_end_time = time(NULL);
ev.data.ptr = ptask;
ev.events=EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
else
{
std::cout << "not end" << std::endl;
}
}
}
else if(events.events&EPOLLOUT)
{
ptask = (http_task*)events.data.ptr;
sockfd = ptask->fd;
if (ptask->write_begin_time == 0)
{
ptask->write_begin_time = time(NULL);
}
static char* pSend = HTTP_200_OK;
int writed = write(sockfd, pSend+ptask->Writed, sizeof(HTTP_200_OK)-1-ptask->Writed);
if (strcmp(inet_ntoa(ptask->remoteAddr.sin_addr),"123.125.117.250") == 0)
{
time_t tNow = time( NULL );
char *szTime = asctime( localtime( &tNow ) );
szTime[strlen( szTime ) - 1] = '\0';
std::cout<< szTime <<" writed " << writed <<std::endl;
}
if (writed <= 0)
{
if(errno == EAGAIN)
{
cout << getpid() <<":write EAGAIN" << endl;
ev.data.ptr = ptask;
ev.events=EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
else
{
delete_http_task(epfd,(http_task*)events.data.ptr);
cout << getpid() <<":write error=" << errno << endl;
}
}
else
{
ptask->Writed += writed;
if (ptask->Writed >= sizeof(HTTP_200_OK)-1)
{
delete_http_task(epfd,(http_task*)events.data.ptr);
}
else
{
cout << "need write again..." << endl;
}
}
}
else if(events.events & (EPOLLHUP|EPOLLERR))
{
cout << getpid() <<":EPOLLHUP|EPOLLERR" << endl;
delete_http_task(epfd,(http_task*)events.data.ptr);
}
}
}
return 0;
} |
|