⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soso1.c

📁 网络检索源码
💻 C
字号:
/**
	SQLET WebServer 测试
	http://www.sqlet.com
	mail:199909@gmail.com
 **/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>

#define	 MAX_THREAD		1024
#define  MAX_MUTEX      10
#define  QUEUE_BLOCK	1
#define  LOAD_PAGE_BLOCK	2
#define  READ_TIMEOUT	3000 // 3秒

#define  BUF_SIZE		2048
#define  MAX_PARAM_NAME		16
#define  MAX_PARAM_VALUE	64
#define	 MAX_CMD_LEN		12

typedef struct PARAM_NODE{
        char            name[MAX_PARAM_NAME];
        char            value[MAX_PARAM_VALUE];
        struct 			PARAM_NODE    *next;
}PARAM_NODE;

pthread_t 	    threadML[MAX_THREAD];
sem_t			threadSem[MAX_THREAD];
int				threadFdc[MAX_THREAD];

char        * mime_head ="HTTP/1.0 %d %s\r\nServer: %s\r\nContent-type: %s\r\nConnection: Close\r\n\r\n";
char  		* ptrHomePageBuf = ( char *)0;
int			  iHomePageBufLen = 0 ;
char		* fileHomePage = "index.html";

typedef void* (*StartFun) (void *);
void homePage(int,PARAM_NODE *);
void searchPage(int,PARAM_NODE *);
void errorPage(int ,char *);

struct	listCommand {
		char command[MAX_CMD_LEN+1];
		void  (*cmdFun) ( int,PARAM_NODE * );
}LIST_COMMAND [] = 
{
	{"/" 			,homePage},
	{"/s" 			,searchPage},
	{"/index.html"  ,homePage},
	{"/index.htm"	,homePage},
	{"\0",			NULL}
};

int startThread (StartFun run, int iThreadNum);
int stopThread(int iThreadNum);
void *searcherThread (void *pthreadNum);

int startWebServer (int iHttpPort,int iThreadNum) ;

inline int hexVal(char c) 
{
	if (c >= '0' && c <= '9') return c - '0';
	else if (c >= 'a' && c <= 'f') return c - 'a' + 10;
	else if (c >= 'A' && c <= 'F') return c - 'A' + 10;
	else return 0;
}
inline void strTrim(char str[])
{
  int firstchar=0;
  int endpos=0;
  int i;
  int firstpos=0;

  for(i=0;str[i]!='\0';i++){
    if(str[i]==' ' || str[i] == '\r' || str [i] == '\n' || str [i]=='\t'){
      if(firstchar==0) firstpos++;
    }
    else{
      endpos=i;
      firstchar=1;
    }
  }

  for(i=firstpos;i<=endpos;i++)
    str[i-firstpos]=str[i];
  str[i-firstpos]='\0';
}

void urlUnescape(char *strUrl) 
{
   int i = 0;
   int j = 0;

   while (strUrl[i] != 0) {
	    if ( strUrl[i] == '+' )
	             strUrl[i] =  ' ' ;  /* 空格 */
		if ((strUrl[i] == '%') && (strUrl[i+1] != 0) && (strUrl[i+2] != 0)) {
				strUrl[j] = 16 * hexVal(strUrl[i+1]) + hexVal(strUrl[i+2]);
				i += 3;
		}else {
				strUrl[j] = strUrl[i];
				i++;
		}
      	j++;
     }
   	 strUrl[j] = 0;
}
int splitQuery(char *strUrl, char *strName, char *strValue)
{
	int iPos;
	int i, j,len=0;

	i=0;
	while ((strUrl[i] != '=') && (strUrl[i] != 0) && (strUrl[i] != ' ')) {
			i++;
            len++;
	}
    if (strUrl[i] == '=') {
			iPos = i;

			for (i=0,j=0; i<iPos; i++,j++) {
				if (i == 0 && strUrl [0] == '&')
			    {
			      	strName[j] = strUrl[i+1];
			      	i++;
			    }else strName[j] = strUrl[i];
			}
			strName[j] = 0;

			i = iPos + 1;
			j = 0;
            while (strUrl[i] != 0  && strUrl[i] != ' ' && strUrl[i] != '&') {
                   strValue[j] = strUrl[i];
				   i++;
				   j++;
                   len++;
			}
            strValue[j] = '\0';
			return len;
	}
    return 0;
}
inline long currentTimeMillis()
{
	struct timeval tv;
	
	gettimeofday(&tv, NULL);
	return tv.tv_sec*1000L+tv.tv_usec/1000L;
}


PARAM_NODE *queryParamList(char *strQuery)
{
  PARAM_NODE	*head;
  int    len = 0;
  char   name[MAX_PARAM_NAME],value[MAX_PARAM_VALUE];
  if(strQuery==NULL)
     return (PARAM_NODE *)NULL;
  else{
       len=splitQuery(strQuery,name,value);
       if(len==0)
          return (PARAM_NODE *)NULL;
       urlUnescape(name);
       urlUnescape(value);
       head=(PARAM_NODE *) malloc (sizeof (PARAM_NODE));
       if ( head == (PARAM_NODE *) NULL)
       		return (PARAM_NODE *) NULL;
       strTrim(name);
       strTrim(value);
       strcpy(head->name,name);
       strcpy(head->value,value);
       strQuery = strQuery + len + 1;
       head->next= queryParamList(strQuery);
       return head;
      }
}

void errorPage(int fdc,char *strMessage)
{
	char	bufSocket[BUF_SIZE +1];

	sprintf(bufSocket, mime_head, 200, "OK", "SQLET_Searcher","text/html; charset=gb2312");
	sprintf(bufSocket,"<html><head><title>sqlet</title></head><body><h1>%s</h1></body></html>",strMessage);	
    write(fdc,bufSocket,strlen(bufSocket));
}

void homePage(int fdc ,PARAM_NODE * param)
{
    write(fdc,ptrHomePageBuf,iHomePageBufLen);
}

void searchPage(int fdc,PARAM_NODE * param)
{
	//在这里执行搜索
    write(fdc,ptrHomePageBuf,iHomePageBufLen);
}

int loadFirstPage(int fdc)
{
	//在浏览上发一个命令,server自动把首页的文件载到(更新)内存	,程序一起动的也载到内存
   struct stat ast;
   int   handle;
   char        *filebuf , buf[128];

   if ((handle = open(fileHomePage, O_RDONLY)) < 0)	{
         sprintf(buf,"首页文件(%s)没有找到!",fileHomePage);
         if ( fdc < 1 ) 
         	  return -1;
   }else {
   		fstat(handle, &ast);
   		if ((filebuf = (char *)malloc(ast.st_size + 1))==NULL)
         if ( fdc < 1 ) 
        	 return -1;

   		if ((ast.st_size = read(handle, filebuf, ast.st_size)) < 0) {
        	sprintf(buf,"读文件(%s)出错!", fileHomePage);
        	free(filebuf);
        	filebuf = ( char *)0;
   		} else {
			filebuf[ast.st_size] = '\0';

		    if ( ptrHomePageBuf != ( char *)0)
		    	free(ptrHomePageBuf);
	    	ptrHomePageBuf = &filebuf[0];
	    	iHomePageBufLen = ast.st_size ;
        	sprintf(buf,"首页文件(%s)成功加载到内存!", fileHomePage);
		}
   		close(handle);
	}
	if ( fdc > 0 )		
		errorPage(fdc,buf);
	else printf("%s\n",buf); //在程序启动时加载
	
	return 0;
}

inline int setnonblock(int fdc,int to)
{
	struct timeval timeout;
	
	timeout.tv_sec = to/1000;
	timeout.tv_usec=0;

	if (setsockopt(fdc, SOL_SOCKET, SO_RCVTIMEO,(char*) &timeout, sizeof(timeout)))
		return 0;
	return 1;
}

void *searcherThread (void *pthreadNum)
{
	int	 	i , nThread , fdc ,condition = 1 ,size = 0,lineStartPos = 0;
	char	bufSocket[BUF_SIZE + 1];
	char	strKeyWord[32],strCharset[16] ,*ptrUrl, *ptrQuery ;
	int		iPageNum ;
 	PARAM_NODE *paramList , *ptmp;
	long	tStart =0	, tEnd = 0 ;
	
	nThread = ( int ) pthreadNum ;
 	while ( condition ) 
 	{
		sem_wait(&threadSem[nThread]);
		fdc = threadFdc[nThread];
		if ( fdc < 0 )
			continue;
		tStart = currentTimeMillis();
		bzero((char *) bufSocket, sizeof(bufSocket));
//		setnonblock(fdc, READ_TIMEOUT);
   		size = read(fdc, bufSocket, BUF_SIZE);
   		if ( size < 0)
			size = 0 ;
      	bufSocket[size] = '\0';

		//内容不能超过BUF_SIZE
		if ( ( size == BUF_SIZE) || (bufSocket[0] != 'G' ) || (bufSocket[1] != 'E') || (bufSocket[2] != 'T')) {
			 errorPage(fdc,"请求出错!");
			 threadFdc[nThread] = -1 ;
			 close(fdc);
			 continue;
		}
		
		i = 4 ;
		ptrUrl = &bufSocket[i];
    	ptrQuery = ( char *)0;
		while ( bufSocket[i] != ' ' && bufSocket[i] != '\t' && bufSocket[i] != '\n' && bufSocket[i] != '\r' && bufSocket[i] != '\0')
		{
			if ( bufSocket[i] == '?' ){
				 bufSocket[i] = '\0';	
    		 	if ( bufSocket[i+1]  != '\0')
        	 		 ptrQuery = &bufSocket[i+1];
			}
			i ++ ;	
		}
		bufSocket[i] = '\0';
		i ++ ;
		
		lineStartPos = i ;
    	for ( i = lineStartPos; i <  size ; i ++ )
		{
			if ( bufSocket[i] == '\r' && bufSocket[i+1] == '\n' )
	    	{
	    		if ( strncasecmp( &bufSocket[lineStartPos],"Host:",5) == 0 ) 
	    		{
	    				bufSocket[i] = '\0';
//						printf("found host |%s|\n",&bufSocket[lineStartPos]+6);	    			
	    		}else if ( strncasecmp( &bufSocket[lineStartPos],"Accept-Language:",16) == 0) 
	    		{
	    				bufSocket[i] = '\0';
//	    				printf("found language|%s|\n",&bufSocket[lineStartPos+17]);
	    		}
	    		i += 2 ;
	    		lineStartPos = i ;
	    	}
	    }// end for i

    	paramList = queryParamList (ptrQuery);	

		i = 0 ;
		while ( LIST_COMMAND[i].command[0] != '\0')
		{
			if ( strcmp(LIST_COMMAND[i].command , ptrUrl ) == 0 ) 
			{
				LIST_COMMAND[i].cmdFun(fdc , paramList);	
				break ;
			}
			
			i ++ ;	
		}

		if ( LIST_COMMAND[i].command[0] == '\0' ) 
		{
			 errorPage(fdc,"请求出错,找不到指令!");
		}
    	while( paramList !=NULL )
    	{
    		printf("%s --------%s\n",paramList->name,paramList->value);
    		ptmp = paramList; 
    		paramList  = paramList -> next;
    		free(ptmp);
    		ptmp = ( PARAM_NODE *)NULL;
    	}

		tEnd = currentTimeMillis();
    	printf("THREADNUM:%d|time:%ldms|cmd:%s|query:%s \n",(int)pthreadNum,(tEnd - tStart ),ptrUrl,ptrQuery);

		threadFdc[nThread] = -1 ;
		close(fdc);
 	} // end while ( condition)
}

int startWebServer (int iHttpPort,int iThreadNum) 
{
  int fds , fdc , i = 0 ;
  int iAllowReuse = 1;
  struct sockaddr_in serverAddr , clientAddr;
  int iClientLen = sizeof(serverAddr);

  bzero((char *) &serverAddr, sizeof(struct sockaddr_in));
  serverAddr.sin_addr.s_addr = INADDR_ANY;
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(iHttpPort);

  if ((fds = socket(AF_INET, SOCK_STREAM, 0)) == -1
	  || setsockopt(fds, SOL_SOCKET, SO_REUSEADDR, (char*)&iAllowReuse, sizeof(iAllowReuse))
	  || bind(fds, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) != 0
	  || listen(fds, 8) != 0) {
	printf("Unable to start the WebServer ( errorno:%d ) \n",errno);
	return -1;
  }
  i = 0 ;

  if ( startThread(searcherThread,iThreadNum) < 0)
  	return -1;
  while ( 1 ) {
	printf("accept.....\n");
	fdc = accept(fds, (struct sockaddr *) &clientAddr, (int *)&iClientLen);
	if (fdc == -1) {
	  printf("accept web server error!...\n");
	}
		/**	todo:超过最大线程数,自动建
		**/
	while ( threadFdc[i] >= 0) {
			i ++ ;	
			if ( i >= iThreadNum ){	//队列已满,等待
				 usleep(500);
				 i = 0 ;
			}
	}	
	threadFdc[i] = fdc ;
	sem_post(&threadSem[i]);
	
	i ++ ;
	if ( i >= iThreadNum )
		 i = 0 ;
  } // end while 
  return 0;
}

int startThread (StartFun run, int iThreadNum) 
{
  int i ;
  pthread_attr_t attr;

  for ( i = 0 ; i < iThreadNum ; i ++ ) 
  {
  	printf("thread create %d\n",i);
 	sem_init(&threadSem[i],0,0);
	threadFdc[i] = -1;	

  	if (pthread_attr_init(&attr) != 0
      || pthread_create(&threadML[i], &attr, run, (void *)i) != 0
      || pthread_attr_destroy(&attr) != 0
    //  || pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0
      || pthread_detach(threadML[i]) != 0) 
 //     if ( pthread_create(&threadML[i], NULL, run, (void *)i) != 0)
      {
		printf("创建线程错误:\r\n\r\n");
    	return -1;
  	} // end if
  }// end for i
  
  return 0;
}

int stopThread(int iThreadNum)
{
	int i;
	
	for(i=0; i < iThreadNum; i++)
	{
		if(threadML[i] !=0 )
			pthread_join(threadML[i],NULL);
//		pthread_exit(&i);
	}
}

void sigdie(int a)
{
	printf("\r\n\r\nCaught signal n.%d\r\n\r\n",a);
	if(a==15)
	{
		printf("\r\n退出...\r\n");
		exit(0);
	}
// stopThread(int iThreadNum)

}

int main(void)
{
//	signal(SIGINT,  sigdie);
//	signal(SIGTERM, sigdie);

	if (loadFirstPage( -1 ) < 0 ) {
		printf("找不到默认的首页文件...\n");
		return -1;	
	}
	startWebServer(80,200);	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -