Linux multi-thread Server Source Code

Source: Internet
Author: User

Source code analysis for http://tuoxie174.blog.51cto.com/1446064/413189

# Include <iostream>
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <sys/stat. h>
# Include <netinet/in. h>
# Include <unistd. h>
# Include <pthread. h>
# Include <stdio. h>
# Include <string. h>
# Include <arpa/inet. h>
# Include <stdlib. h>
Using namespace std;

# Define PORT 8848 // Port
# Define BACKLOG 5 // Max Link num
# Define MAXDATASIZE 1000 // Max data buf
# Define DEBUG 1

// 1. Func Decalare
Void process_cli (int connectfd, sockaddr_in client );
Int sendobj (int connectfd, char * serverfilepath );
Int isDIR (char * path );
Int fileordirExist (char * fpath );
Char * gettextname (char *);
Int writehead (FILE * cfp, char * extname );
Void * start_routing (void * arg );
Void msg404 (int connectfd );

// 2. Structure Decalare
Struct ARG
{
Int connfd;
Sockaddr_in client;
};


Int main ()
{
// Cout <"Hello world! "<Endl;
Int listenfd, connectfd;
//! 1. thread id
Pthread_t thread;
//! 2. pass this var to the thread
ARG * arg;
Struct sockaddr_in server;
Struct sockaddr_in client;
Int sin_size;

//! 3. create tcp socket
# Ifdef DEBUG
Printf ("socket... \ n ");
# Endif
If (listenfd = socket (AF_INET, SOCK_STREAM, 0) =-1)
{
Perror ("creating socket failed! \ N ");
Exit (1 );
}
//! 4. set the socket -- close, timeout
Int opt = SO_REUSEADDR;
Setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, & opt, sizeof (opt ));
Bzero (& server, sizeof (server ));

Server. sin_family = AF_INET;
Server. sin_port = htons (PORT );
Server. sin_addr.s_addr = htonl (INADDR_ANY );

Printf ("bind... \ n ");
//! 5. bind a ip and port to the socket
If (bind (listenfd, (struct sockaddr *) & server, sizeof (struct sockaddr )))
{
Perror ("bind error! ");
Exit (1 );
}

Printf ("listen... \ n ");
//! 6. listen the socket
If (listen (listenfd, BACKLOG) =-1)
{
Perror ("listen error! \ N ");
Exit (1 );
}

// A datastructure for programmer to use struct sockaddr
Sin_size = sizeof (struct sockaddr_in );
While (1)
{
// Begin to process the client's connect
//! 7. accept using main thread
Printf ("accepting... \ n ");

If (connectfd = accept (listenfd, (struct sockaddr *) & client, (socklen_t *) & sin_size) =-1)
{
Printf ("accept error! \ N ");
}

// Connectfd is a socket
Arg = new ARG;
Arg-> connfd = connectfd;
Memcpy (void *) & arg-> client, & client, sizeof (client ));

# Ifdef DEBUG
Printf ("thread creating... \ n ");
# Endif
//! 8. invoke start_routing to handle this thread. -- start_routing is a callback func
If (pthread_create (& thread, NULL, start_routing, (void *) arg ))
{
Perror ("pthread_create error! \ N ");
Exit (1 );
}

}
Close (listenfd );

Return 0;
}

//! 1.1 handle the request
Void process_cli (int connectfd, sockaddr_in client)
{
Int num;
Char requestline [MAXDATASIZE];
Char filepath [MAXDATASIZE];
Char cmd [MAXDATASIZE];
Char extname [MAXDATASIZE];

Int c;
FILE * fp;
//! Because everything is file in UNIX
//! 1.1.1 open the client socket
Fp = fdopen (connectfd, "r ");

# Ifdef DEBUG
Printf ("the host is: % s \ n", inet_ntoa (client. sin_addr ));
# Endif
Fgets (requestline, MAXDATASIZE, fp );

# Ifdef DEBUG
Printf ("The request is: % s \ n", requestline );
# Endif

Strcpy (filepath ,"./");
Sscanf (requestline, "% s \ n", cmd, filepath + 2 );
//! Use func gettextname
Strcpy (extname, gettextname (filepath ));

# Ifdef DEBUG
Printf ("cmd: % s \ n filepath: % s \ n extname: % s \ n", cmd, filepath, extname );
Printf ("string comparing \ n :::::: start ::::::::\ n ");
# Endif

If (strcmp (cmd, "GET") = 0)
{
# Ifdef DEBUG
Printf ("cmd (% s) = GET \ n", cmd );
# Endif

If (fileordirExist (filepath ))
{
If (isDIR (filepath ))
{
//! Is a DIR
# Ifdef DEBUG
Printf ("% s is a DIR \ n", filepath );
# Endif
If (fileordirExist (strcat (filepath, "index.html ")))
{
//! Send
Sendobj (connectfd, "index.html ");
}
Else
{
Msg404 (connectfd );
}
}
Else
{
//! Is a file
# Ifdef DEBUG
Printf ("% s is a file \ n", filepath );
# Endif
//! Send
Sendobj (connectfd, filepath );
}
}
Else
{
# Ifdef DEBUG
Printf ("404 \ n ");
# Endif
Msg404 (connectfd );
}
}
Else
{
# Ifdef DEBUG
Printf ("cmd (% s )! = GET \ n ", cmd );
# Endif
}
# Ifdef DEBUG
Printf ("::::::::::::::::::: end ::::::::::::::::: \ n ");
Close (connectfd );
# Endif
}

//! 1.2
Void msg404 (int connectfd)
{
Char * msg;
Msg = "HTTP/1.0 404 Not Found Content-Type: text/plain 404 not found by Manio \ n ";
Send (connectfd, msg, strlen (msg), 0 );
}

//! 1.3 is the filepath a file or direatory
Int fileordirExist (char * fpath)
{
Struct stat filestat;
Return (stat (fpath, & filestat )! =-1 );
}

//! 1.4 is the filepath a directory
Int isDIR (char * fpath)
{
# Ifdef DEBUG
Printf ("IN IsDir \ ns ");
# Endif
Struct stat filestat;
Return (stat (fpath, & filestat )! =-1 & S_ISDIR (filestat. st_mode ));
}

//! 1.5 send the data of the file which the client want
Int sendobj (int connectfd, char * serverfilepath)
{
// Printf ("server: % s \ n", serverfilepath)
FILE * sfp = NULL, * cfp = NULL;
Char c;
Sfp = fopen (serverfilepath, "r ");
Cfp = fdopen (connectfd, "w ");

If (sfp = NULL)
Printf ("can't open the file !... \ N ");
If (cfp = NULL)
Printf ("can't open the link file ...! \ N ");

Writehead (cfp, gettextname (serverfilepath ));

While (c = getc (sfp ))! = EOF ){
Putc (c, cfp );
// Putchar (c );
}
Fflush (cfp );
Return 0;
}

//! 1.6 write the packet header to the client
Int writehead (FILE * cfp, char * extname)
{
# Ifdef DEBUG
Printf ("INWRITEHEAD ::::: extname is % s ::::::\ n", extname );
# Endif
Char * content = "text/plain ";
If (strcmp (extname, "html") = 0 | strcmp (extname, "htm") = 0)
Content = "text/html ";
Else if (strcmp (extname, "css") = 0)
Content = "text/css ";
Else if (strcmp (extname, "gif") = 0)
Content = "image/gif ";
Else if (strcmp (extname, "jpeg") = 0 | strcmp (extname, "jpg") = 0)
Content = "image/jpeg ";
Else if (strcmp (extname, "png") = 0)
Content = "image/png ";

# Ifdef DEBUG
Printf ("HTTP/1.1 200 OK \ n ");
Printf ("Content-Type: % s \ n", content );
# Endif

Fprintf (cfp, "HTTP/1.1 200 OK ");
Fprintf (cfp, "Content-Type: % s \ n", content );

Return 0;
}

//! 1.7 get the extent name of the file
Char * gettextname (char * filepath)
{
Char * p;
If (p = strrchr (filepath ,'.'))! = NULL)
Return p + 1;
Return NULL;
}

//! 1.8 invoked by pthread_create
Void * start_routing (void * arg)
{
ARG * info;
Info = (ARG *) arg;
// Handle client's requirement
Process_cli (info-> connfd, info-> client );
Delete arg;
Pthread_exit (NULL );
}

// 1. As long as g ++-g-o execname filename-lpthread

// 2. enter 127.0.0.1: 8848 in the browser

// 3. There is an index.html extension in the same directory as the program. The extension must be determined in the program)

Problem: Garbled characters may occur in Chinese. Check the source code and find that a large part of the





















 

This article is from the coffee time blog, please be sure to keep this source http://tuoxie174.blog.51cto.com/1446064/413683

Related Article

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.