?? sockcommon.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 + -