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

📄 sockcommon.cpp

📁 PDA版的小型WEB服务器
💻 CPP
字号:
#include "stdafx.h"
#include "SockCommon.h"
#include "trace.h"
#include <WinSock2.h>
#include <string.h>
#include <assert.h>

#define SUCCESS TRUE
#define FAILURE	FALSE

char cDefaultPage[]= "index.html";char cHostBasePath[]="webRoot";


char* strDup(char const* str) {	if (str == NULL) return NULL;	size_t len = strlen(str) + 1;  	char* copy = new char[len];	if (copy != NULL) {		memcpy(copy, str, len);	}	return copy;}
// listening thread;
UINT ServerListenThread(LPVOID lpv){

	log("listen");
	//
	SOCKET listenSock = *((SOCKET*)lpv);

	struct sockaddr_in client;

	// Optional pointer to an integer that contains the length of addr.
	int size;

	// Create a SOCKET for accepting incoming requests.
	SOCKET acceptSock;

	//log
	log("begin to listen");

	do
	{
		size = sizeof client;
		acceptSock = accept( listenSock, (struct sockaddr*)&client, &size );

		if ( acceptSock != INVALID_SOCKET )
		{
			AfxBeginThread( HttpCommunicate,(LPVOID)&acceptSock,THREAD_PRIORITY_NORMAL);
		}
	}while(1);
}


// receive request;
boolean Receive(SOCKET acceptScok,char *pRecvBuffer, int nRecvSize, int nSecs){
	ASSERT(acceptScok != NULL);
	int nReceivedSize = 0;
	if ( (nReceivedSize = recv(acceptScok,pRecvBuffer,nRecvSize,0)) == SOCKET_ERROR )
	{
		AfxMessageBox(_T("socket receive!"));
		log("socket receive!");
		return FAILURE;
	}
	return SUCCESS;
}

// parse the http request line;
HttpHeader parseRequestLine(char* pRequestLine){
	//
	char* pRequest = new char[strlen(pRequestLine)+1];
	strcpy( pRequest,pRequestLine );
	strcat( pRequest,"\0" );
	
	// change the upper case charactors to lower case;
	#define strlwr _strlwr
	strlwr( pRequest );

	HttpHeader head;
	char* pHead = pRequest;
	char* pEnd;
	int nCount = 0;
	
	// skip over the white space;
	while( *pHead == ' ' ) pHead++;
	pEnd = strchr( pHead,' ' );
	nCount =  pEnd -pHead;
	if ( nCount >0 )
	{
		strncpy( head.RequestMethod,pHead,nCount );
		head.RequestMethod[nCount] = '\0';
	}
	if ( strcmp( head.RequestMethod,"post" ) != 0 && strcmp( head.RequestMethod,"get" ) != 0 )
	{
		delete[] pRequest;
		head.IsValid = TRUE;
		return head;
	}else{
		head.IsValid = TRUE;
	}

	// get file path;
	pHead = pEnd;
	while( *pHead == ' ' ) pHead++;
	pEnd = strchr( pHead,' ' );
	nCount =pEnd - pHead ;
	if ( nCount > 0 )
	{
		strncpy( head.FilePath,pHead,nCount );
		head.FilePath[nCount] = '\0';
	}

	// http version;
	pHead = pEnd;
	while( *pHead == ' ' ) pHead++;
	pEnd = strchr( pHead,'\n' );
	nCount = pEnd - pHead;
	if (nCount > 0 )
	{
		strncpy( head.HttpVersion,pHead,nCount );
		head.HttpVersion[nCount] = '\0';
	}

	// get reference;
	if ( pHead = strstr( pRequest,"referer:") )
	{
		pHead += 8;
		while( *pHead == ' ' ) pHead++;
		pEnd = strchr( pHead,'\n' );
		nCount = pEnd - pHead;
		if (nCount > 0 )
		{
			strncpy( head.Referer,pHead,nCount-1 );
			head.Referer[nCount - 1] = '\0';
		}
	}else{
		memset( head.Referer,0,sizeof(head.Referer));
	}

	// get host;
	pHead = pRequest;
	pHead = strstr( pHead,"host:" );
	pEnd = strchr( pHead,'\n' );
	pHead += 5;
	while( *pHead == ' ' ) pHead++;
	nCount = pEnd - pHead;
	if (nCount > 0 )
	{
		strncpy( head.Host,pHead,nCount-1 );
		head.Host[nCount-1] = '\0';
	}

	// parse the file name;
	pHead = head.FilePath;
	pHead = strchr( pHead,'?' );
	if ( pHead )
	{
		strcpy( head.QueryString,pHead+1 );
		*(pHead + 1) = '\0';
	}

	// parse the relative path;
	pHead = head.FilePath;
	if ( strchr(pHead,'.'))
	{
		if ( pHead = strrchr( pHead,'/' ) )
		{
			strcpy( head.FileName,pHead+1 );
			*(pHead + 1) = '\0';
		}
	}else
		head.FileName[0] = '\0';
	

	// when the method is post , parse out the parameter;
	if(strcmp(head.RequestMethod,"post")==0)
	{
		pHead=pRequest;
		pHead=strstr(pHead,"content-length:");
		pEnd=strchr(pHead,'\n');
		pHead+=15;
		while(*pHead==' ')pHead++;
		nCount=pEnd-pHead;
		if(nCount)
		{
			char temp[10];
			strncpy(temp,pHead,nCount);
			temp[nCount]='\0';
			head.ContentLength=atoi(temp);
		}
		pHead=pRequest;
		if(pHead=strrchr(pHead,'\n'))
		{	
			strncpy(head.Parameter,pHead+1,head.ContentLength);//直接复制到尾即可
			head.Parameter[head.ContentLength]='\0';
		}
	}
	else//Get时了最好赋一下初值。
	{
		head.ContentLength=0;
		head.Parameter[0]='\0';
	}
	delete[] pRequest;
	return head;
	

}

//
//char* GetLocationHead(int nStatusCode,const char* pStatusDesStr,const char *pLocationUrl,char* pRtnVal)
//{
//	char cHeadFmt[]=
//		"HTTP/1.1 %d %s\r\n"
//		"Server: AnyServerMoblieHttpServer/1.0.0\r\n"
//		"Date: %s\r\n"
//		"Location:%s\r\n"
//		"Content-Type: text/html\r\n"
//		"Accept-Ranges: bytes\r\n";
//	char cHead[500];
//	CString strGmtNow=CTime::GetCurrentTime().FormatGmt(TEXT("%a, %d %b %Y %H:%M:%S GMT"));
//	sprintf(cHead,cHeadFmt,nStatusCode,pStatusDesStr,(LPSTR)(LPCTSTR)strGmtNow,pLocationUrl);
//	strcat(cHead,"\r\n");
//	strcpy(pRtnVal,cHead);
//	return pRtnVal;
//}


// 
//void SendLocationHead(SOCKET msSocket,const int nStatusCode,const char *pStatusDesStr,const char *pLocationUrl)
//{
//	char *pHead=new char[500];
//	GetLocationHead(nStatusCode,pStatusDesStr,pLocationUrl,pHead);
//	ConfirmSend(msSocket,pHead,strlen(pHead),10);
//	delete[] pHead;
//}


char* GetResponseHead(int nStatusCode,const char* pStatusDesStr,const char* szTypeName,
					  const char* pFileModifyTime,int nResponseContextSize,char* pRtnVal)
{
	char cHeadFmt[]=
		"HTTP/1.1 %d %s\r\n"
		"Server: Braveboy HttpServer\r\n"
		"Date: %s\r\n"
		"Content-Type: %s\r\n"
		"Accept-Ranges: bytes\r\n"
		"Content-Length: %d\r\n";
	char cHead[500];
	CString strGmtNow=CTime::GetCurrentTime().FormatGmt(TEXT("%a, %d %b %Y %H:%M:%S GMT"));
	sprintf(cHead,cHeadFmt,nStatusCode,pStatusDesStr,GetGmtTime(),szTypeName,nResponseContextSize);
	if(!pFileModifyTime)
	{
		char hdrModified[50];
		sprintf(hdrModified, "Last-Modified: %s\r\n\r\n",pFileModifyTime);
		strcat(cHead,hdrModified);
	}
	strcat(cHead,"\r\n");
	strcpy(pRtnVal,cHead);
	return pRtnVal;
}



//
void SendHead(SOCKET msSocket,const int nStatusCode,const char* szTypeName,
			  const char *pStatusDesStr, const char* pFileModifyTime,int nHtmlSize,const char *pErrorDetailMsg)
{
	char *pHead=new char[500];
	if(pErrorDetailMsg!=NULL)
	{
		char cErrorHtml[]="<Html>\n"
			"<Head><Title>HTTP %d (%s)</Title>\n"
			"</Head>\n"
			"<Body>\n"
			"<h1>%s</h1>\n"
			"<h2>错误详细描述:%s</h2>\n"
			"</Body>\n"
			"</Html>";
		char cErrorBody[500];
		sprintf(cErrorBody,cErrorHtml,nStatusCode,pStatusDesStr,pStatusDesStr,pErrorDetailMsg);
		GetResponseHead(nStatusCode,pStatusDesStr,szTypeName,pFileModifyTime,strlen(cErrorBody),pHead);
		ConfirmSend(msSocket,pHead,strlen(pHead),10);	
		ConfirmSend(msSocket,cErrorBody,strlen(cErrorBody),10);
	}
	else
	{

		GetResponseHead(nStatusCode,pStatusDesStr,szTypeName,pFileModifyTime,nHtmlSize,pHead);
		ConfirmSend(msSocket,pHead,strlen(pHead),10);
	}
	delete[] pHead;
}

int ConfirmSend(SOCKET s_socket,const char *pBuffer, int nSendSize, int nSecs)
{
	int nSendBytes=0;
	int nSendedBytes=0;
	const char*p=pBuffer; 
	do
	{
		nSendBytes=Send(s_socket,p,nSendSize-nSendedBytes,nSecs);
		nSendedBytes+=nSendBytes;
		p+=nSendBytes;
	}
	while(nSendedBytes<nSendSize);
	return nSendedBytes;
}

int Send(SOCKET s_socket,const char *pBuffer, int nSendSize, int nSecs)
{
	ASSERT(s_socket!=NULL);
	FD_SET fd = {1, s_socket};
	TIMEVAL tv = {nSecs, 0};
	if(select(0, NULL, &fd, NULL, &tv) == 0){
		AfxMessageBox(_T("socket send timeout"));
		log("socket send timeout!");
		return 0;
	}
	int nSendBytes=0;
	nSendBytes=send(s_socket,pBuffer,nSendSize,NULL);
	return nSendBytes;
}

//获得文件扩展名
char* GetFileExtName(char *pFileName)
{
	//const char *pFileName="abc.asp";
	char *pExt;
	pExt=strrchr(pFileName,'.');
	if(pExt)
		return ++pExt;
	else
		return NULL;
}

void initialHeader(HttpHeader *head){
	head->ContentLength = 0;
	head->IsValid = NULL;
	memset( head->FileName,0,sizeof(head->FileName));
	memset( head->FilePath,0,sizeof(head->FilePath));
	memset( head->Referer,0,sizeof(head->Referer));
	memset( head->Host,0,sizeof(head->Host));
	memset( head->HttpVersion,0,sizeof(head->HttpVersion));
	memset( head->QueryString,0,sizeof(head->QueryString));
	memset( head->Language,0,sizeof(head->Language));
	memset( head->Parameter,0,sizeof(head->Parameter));
}

// begin to communicate with client;
UINT HttpCommunicate(LPVOID lpv){
	//
	//
	SOCKET acceptScok = *(SOCKET*)lpv;
	char* pRequestLine = new char[1000];
	// get the request frow client browser;
	if( Receive(acceptScok,pRequestLine,1000,1000) == FAILURE )
	{
		AfxMessageBox(_T("socket receive failed!"));
		log("socket receive failed!");
		return 0;
	}

	log("receive success");

	// parse the request line;
	HttpHeader head = parseRequestLine(pRequestLine);

	// the wrong format of request line;
	if( !head.IsValid )
		return 0;

	//delete[] pRequestLine;
	//检查页面及路径是否存在
	//如果请求里面没有带具体的页面信息
	if(!(*head.FileName))
	{
		////检查默认页面如果被设置,且默认页面都存在,则发送默认页面,否则发送403错误!
		char fName[]= "index.html";
		strcpy( head.FileName,fName );

		log(head.FileName);
	}

	char csFilePath[100] = "webRoot\\";
	strcat(csFilePath, "\\");
	strcat( csFilePath ,head.FileName );
	CFile* pFile=Openfile( csFilePath );


	log( (LPSTR)(LPCTSTR)csFilePath );
	log("open request file success");

	char szTypeName[50];

	if(pFile!=NULL)
	{
		//对后缀判断选择不同的方法进行处理
		char *pFileExtName=GetFileExtName(head.FileName);
		if (strcmp( pFileExtName,"html")==0 || strcmp( pFileExtName,"htm")==0 )
		{
			strcpy( szTypeName,"text/html");
		}else if (strcmp( pFileExtName,"mp3")==0)
		{
			strcpy( szTypeName,"audio/mp3");
		}
		else{
			//DeleteDstFile(head.FileName,pFileExtName);
			//strcpy( szTypeName,"video/x-ms-asf");//application/octet-stream//application/x-mms-framed//video/x-ms-wmv
			strcpy( szTypeName,"video/x-ms-asf");
		}

		int nFileSize=(int)pFile->GetLength();

		CString strGmtMod=CTime::GetCurrentTime().FormatGmt(TEXT("%a, %d %b %Y %H:%M:%S GMT"));
		SendHead(acceptScok,200,szTypeName,"OK",(LPSTR)(LPCTSTR)strGmtMod.GetBuffer(0),nFileSize,NULL);
		SendFile(acceptScok,pFile);
		log("send file success");
		pFile->Close();
		//}
	}
	else
	{
		//内部程序处理错误
		//pFile->Close();
		SendHead(acceptScok,505,"text/html","错误",NULL,NULL,"文件不存在!");
	}
	delete pFile;
	Close(acceptScok);

	return 0;
}

CFile* Openfile(char *pFileName)
{
	CFile* pFile= new CFile();
	CFileException e;
	if(pFile->Open(CString(pFileName),CFile::modeRead,&e))
		return pFile;
	if(e.m_cause==CFileException::accessDenied||e.m_cause==CFileException::badPath)
	{
		delete pFile;
	}
	return NULL;
}

void Close(SOCKET s_socket)
{
	if(s_socket==NULL||s_socket==INVALID_SOCKET)return ;
	ASSERT(s_socket!=NULL);
	if(closesocket(s_socket)==SOCKET_ERROR)
	{
		AfxMessageBox(_T("Socket Close!"));
		log("Socket Close!");
		return;
	}
}

void SendFile(SOCKET msSocket,CFile* pFile)
{
	int nFileSize=(int)pFile->GetLength();
	//以最大50K的方式发送文件内容
	char* pFileContext=new char[50*MaxBufferSize];
	int nSizeToBeRead=nFileSize;//还要读的文件大小
	int nReadSize=0;//当前要读的内容大小
	while(nSizeToBeRead>0)
	{	
		nReadSize=min(MaxBufferSize*50,nSizeToBeRead);
		memset(pFileContext,0,MaxBufferSize*50);
		pFile->Read(pFileContext,nReadSize);
		nSizeToBeRead-=nReadSize;
		ConfirmSend(msSocket,pFileContext,nReadSize,10);
	}
	delete[] pFileContext;
}



⌨️ 快捷键说明

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