EPOLL-based HTTP server (added to the thread pool) _ decline capital _ Sina Blog

Source: Internet
Author: User
Tags strtok

EPOLL-based HTTP server (added to the thread pool) _ decline capital _ Sina Blog

EPOLL-based HTTP server (added to thread pool)
(19:02:51)
Reprinted token
Tags:
Miscellaneous
Category: EPOLL
# Include <fcntl. h>
# Include <cstdio>
# Include <unistd. h>
# Include <cstdlib>
# Include <sys/socket. h>
# Include <sys/epoll. h>
# Include <netinet/in. h>
# Include <arpa/inet. h>
# Include <errno. h>
# Include <cstring>
# Include <pthread. h>
Const int EPOLL_SIZE = 5000;
Const int EVENT_ARR = 5000;
Const int PORT = 8002;
Const int BUF_SIZE = 5000;
Const int BACK_QUEUE = 100;
Const int thread_max= 100;
Static unsigned int s_thread_para [THREAD_MAX] [8]; // thread parameters
Static pthread_t s_tid [THREAD_MAX]; // thread ID
Pthread_mutex_t s_mutex [THREAD_MAX]; // thread lock
Int epFd; // epoll
Struct epoll_event ev, evs [EVENT_ARR];
Char * get_type (char * url, char * buf)
{
Const char * t = url + strlen (url );
Char type [64];
For (; t> = url & * t! = '.'; -- T );
Strcpy (type, t + 1 );
If (strcmp (type, "html") = 0 | strcmp (type, "htm") = 0)
Sprintf (buf, "text/% s", type );
Else if (strcmp (type, "gif") = 0 |
Strcmp (type, "jpg") = 0 |
Strcmp (type, "jpeg") = 0 |
Strcmp (type, "png") = 0)
Sprintf (buf, "image/% s", type );
Else if (strcmp (type, "/") = 0)
Sprintf (buf, "text/html ");
Else if (strcmp (type, "css") = 0)
Sprintf (buf, "text/css ");
Else if (strcmp (type, "js") = 0)
Sprintf (buf, "application/x-javascript ");
Else
{

Sprintf (buf, "unknown ");
}
Return buf;
}
Void * http_server (int thread_para [])
{
Int pool_index; // thread pool ID
Int clientFd; // client socket
Char buf [BUF_SIZE];
Pthread_detach (pthread_self ());
Pool_index = thread_para [7];
Wait_unlock:
Pthread_mutex_lock (s_mutex + pool_index); // wait for thread unlock
ClientFd = thread_para [1]; // client socket ID
// Tentatively read data first
Int len = read (clientFd, buf, BUF_SIZE );
Printf ("% s", buf );
If (len> 0)
{
Char * token = strtok (buf, ""); // GET
Printf ("token: % s", token );
Char type [64];
Char * url = strtok (NULL, ""); // URL
While (* url = '.' | * url = '/') + + url;
Printf ("url: % s", url );
Char file [1280000];
Sprintf (file, "% s", url );
Printf ("file: % s", file );
FILE * fp = fopen (file, "rb ");
If (fp = 0)
{
Char response [] = "HTTP/1.1 404 not found \ r \ n ";
Printf ("HTTP/1.1 404 not found \ r \ n ");
Write (clientFd, response, strlen (response ));
}
Else
{
Int file_size;
Char * content;
Char * response;
Fseek (fp, 0, SEEK_END );
File_size = ftell (fp );
Fseek (fp, 0, SEEK_SET );
Content = (char *) malloc (file_size + 1 );
Response = (char *) malloc (200 );
Fread (content, file_size, 1, fp );
Content [file_size] = 0;
Sprintf (response, "HTTP/1.1 200 OK \ r \ nContent-Length: % d \ r \ nContent-Type: % s \ r \ n", file_size, get_type (url, type ));
// Printf ("HTTP/1.1 200 OK \ r \ nContent-Type: % s \ r \ nContent-Length: % d \ r \ n % s ", get_type (url, type), file_size, content );
Write (clientFd, response, strlen (response ));
Write (clientFd, content, file_size );
Free (content );
Free (response );
}
}
Else if (len = 0)
{
// The EPOLL event is triggered but not read, which indicates disconnection.
// Printf ("Client closed at % s \ n", inet_ntoa (clientAddr. sin_addr ));
Epoll_ctl (epFd, EPOLL_CTL_DEL, clientFd, & ev );
Close (clientFd );
Int I = thread_para [3];
Evs [I]. data. fd =-1;
}
Else if (len = EAGAIN)
{
Printf ("socket huan cun man le! \ N ");
}
Else
{
// An error occurred while reading the client.
Printf ("Client read failed! \ N ");
}
Thread_para [0] = 0; // sets the thread occupation flag to "idle"
Goto wait_unlock;
Printf ("pthread exit! \ N ");
Pthread_exit (NULL );
}
Static int init_thread_pool (void)
{
Int I, rc;
For (I = 0; I <THREAD_MAX; I ++)
{
S_thread_para [I] [0] = 0; // idle
S_thread_para [I] [7] = I; // thread pool ID
Pthread_mutex_lock (s_mutex + I); // thread lock
}
// Create thread pool
For (I = 0; I <THREAD_MAX; I ++)
{Rc = pthread_create (s_tid + I, 0, (void * (*) (void *) & http_server, (void *) (s_thread_para [I]);
If (0! = Rc)
{Fprintf (stderr, "Create thread failed! \ N ");
Return-1;
}
}
Return 0;
}
Void setnoblock (int sockFd) // sets the non-blocking mode.
{
Int opt;
If (opt = fcntl (sockFd, F_GETFL) <0) // obtain the original flag;
{
Printf ("get fl failed! \ N ");
Exit (-1 );
}
Opt | = O_NONBLOCK;
If (fcntl (sockFd, F_SETFL, opt) <0)
Printf ("set fl failed! \ N ");
}
Int main ()
{
Int serverFd, j;
ServerFd = socket (AF_INET, SOCK_STREAM, 0); // create a server fd
Setnoblock (serverFd); // set to non-blocking mode
Unsigned int optval;
Struct linger optval1;
// Set the SO_REUSEADDR option (fast server restart)
Optval = 0x1;
Setsockopt (serverFd, SOL_SOCKET, SO_REUSEADDR, & optval, 4 );
// Set the SO_LINGER option (prevent CLOSE_WAIT from hanging all sockets)
Optval1.l _ onoff = 1;
Optval1.l _ linger = 60;
Setsockopt (serverFd, SOL_SOCKET, SO_LINGER, & optval1, sizeof (struct linger ));
// Create an epoll and put serverFd In the listener queue
EpFd = epoll_create (EPOLL_SIZE );
Ev. data. fd = serverFd;
Ev. events = EPOLLIN | EPOLLET;
Epoll_ctl (epFd, EPOLL_CTL_ADD, serverFd, & ev );
// Bind the server port
Struct sockaddr_in serverAddr;
Socklen_t serverlen = sizeof (struct sockaddr_in );
ServerAddr. sin_addr.s_addr = htonl (INADDR_ANY );
ServerAddr. sin_port = htons (PORT );
If (bind (serverFd, (struct sockaddr *) & serverAddr, serverlen ))
{
Printf ("BIND failed! \ N ");
Exit (-1 );
}
// Thread pool Initialization
Int rc = init_thread_pool ();
If (0! = Rc) exit (-1 );
// Enable the listener
If (listen (serverFd, BACK_QUEUE ))
{
Printf ("Listen failed! \ N ");
Exit (-1 );
}
// Service Processing
Int clientFd;
Sockaddr_in clientAddr;
Socklen_t clientlen;
For (;;)
{
// Wait for the epoll event to arrive. A maximum of EVENT_ARR events can be retrieved.
Int nfds = epoll_wait (epFd, evs, EVENT_ARR,-1 );
// Process the event
For (int I = 0; I <nfds; I ++)
{
If (evs [I]. data. fd = serverFd & evs [I]. events & EPOLLIN)
{
// If serverFd is used, a new connection is established.
If (clientFd = accept (serverFd, (struct sockaddr *) & clientAddr, & clientlen) <0)
{
Printf ("ACCEPT failed \ n ");
}
Printf ("Connect from % s: % d \ n", inet_ntoa (clientAddr. sin_addr), htons (clientAddr. sin_port ));
Setnoblock (clientFd );
// Register the connection from accept ()
Ev. data. fd = clientFd;
Ev. events = EPOLLIN | EPOLLET;
Epoll_ctl (epFd, EPOLL_CTL_ADD, clientFd, & ev );
}
Else if (evs [I]. events & EPOLLIN)
{
// If it is not serverFd, the client is readable.
Printf ("client can write! \ N ");
If (clientFd = evs [I]. data. fd)> 0)
{
// Query the idle Thread Pair
For (j = 0; j <THREAD_MAX; j ++ ){
If (0 = s_thread_para [j] [0]) break;
}
If (j> = THREAD_MAX ){
Fprintf (stderr, "the thread pool is full and the connection will be dropped \ r \ n ");
Shutdown (clientFd, SHUT_RDWR );
Close (clientFd );
Continue;
}
// Copy related parameters
S_thread_para [j] [0] = 1; // set the activity flag to "activity"
S_thread_para [j] [1] = clientFd; // Client Connection
S_thread_para [j] [2] = serverFd; // service index
S_thread_para [j] [3] = I; // epoll event id;
// Unlock the thread
Pthread_mutex_unlock (s_mutex + j );}
Else printf ("other error! \ N ");
}
}
}
Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.