“c++實現的Mini Web Server,暫時當ftp使用” —續 (Linux版)

來源:互聯網
上載者:User


本文接 <c++實現的Mini Web Server,暫時當ftp使用> 給出Mini WebServer for Ftp的linux版本。

 

 

 

 

 

 

Linux版miniweb下載:miniweb_linux.tar.gz

 

 

 

關鍵代碼:

 

和Windows版的主要區別在於IoUtil.cpp檔案中關於檔案目錄資訊的讀取部分,其他地方只有細微的改動,在此只給出IoUtil.cpp的代碼:

#include "stdafx.h"<br />#include "IoUtil.h"<br />#include "Constant.h"<br />#if defined WIN32<br />#include <Windows.h><br />#else<br />#include <dirent.h><br />#include <sys/stat.h><br />#include <time.h><br />#endif<br />const char* MONTH_NAME[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",<br /> "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};<br />IoUtil::IoUtil(void)<br />{<br /> m_path = "";<br />}<br />IoUtil::IoUtil( const char* path )<br />{<br /> m_path = path;<br />}<br />IoUtil::~IoUtil(void)<br />{<br />}<br />int IoUtil::Dir( FILELIST_VECTOR& filelist )<br />{<br />#if defined WIN32<br /> filelist.clear();<br /> char pathMask[MAX_PATH_LENGTH];<br /> strcpy(pathMask, m_path.c_str());<br /> strcat(pathMask, "//*");<br /> WIN32_FIND_DATA fileData;<br /> HANDLE hSearch;<br /> bool fFinished = false;<br /> SYSTEMTIME systemtime;<br /> FILETIME filetime;<br /> long long filesize;<br /> FILE_INFO_ST fileitem;<br /> FILELIST_VECTOR tmpList;<br /> ///////<br /> hSearch = FindFirstFile( pathMask, &fileData );<br /> if(hSearch == INVALID_HANDLE_VALUE)<br /> return -1;<br /> while(!fFinished)<br /> {<br /> if(!(fileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))<br /> {<br /> FileTimeToLocalFileTime(&fileData.ftLastWriteTime, &filetime);<br /> FileTimeToSystemTime(&filetime, &systemtime);<br /> filesize = fileData.nFileSizeHigh;<br /> filesize = filesize << 32;<br /> filesize = filesize + fileData.nFileSizeLow;<br /> if((filesize>>50) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024 * 1024 * 1024 * 1024));<br /> sprintf(fileitem.filesize, "%I64d.%I64d PB", filesize>>50, decimal);<br /> }<br /> else if((filesize>>40) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024 * 1024 * 1024));<br /> sprintf(fileitem.filesize, "%I64d.%I64d TB", filesize>>40, decimal);<br /> }<br /> else if((filesize>>30) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024 * 1024));<br /> sprintf(fileitem.filesize, "%I64d.%I64d GB", filesize>>30, decimal);<br /> }<br /> else if((filesize>>20) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024));<br /> sprintf(fileitem.filesize, "%I64d.%I64d MB", filesize>>20, decimal);<br /> }<br /> else if((filesize>>10) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024));<br /> sprintf(fileitem.filesize, "%I64d.%I64d KB", filesize>>10, decimal);<br /> }<br /> else<br /> sprintf(fileitem.filesize, "%I64d B", filesize);<br /> //sprintf(fileitem.filesize, "%I64d.%d", filesize>>10, decimal);<br /> sprintf(fileitem.lastmodifiedtime, "%02d-%s-%4d %02d:%02d",<br /> systemtime.wDay,<br /> MONTH_NAME[systemtime.wMonth - 1],<br /> systemtime.wYear,<br /> systemtime.wHour,<br /> systemtime.wMinute);<br /> sprintf(fileitem.filename, "%s", fileData.cFileName);<br /> if(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)<br /> {<br /> sprintf(fileitem.attribute, "%s", "DIR");<br /> filelist.push_back(fileitem);<br /> }<br /> else<br /> {<br /> sprintf(fileitem.attribute, "%s", "---");<br /> tmpList.push_back(fileitem);<br /> }<br /> }<br /> if(!FindNextFile(hSearch, &fileData))<br /> {<br /> if(GetLastError() == ERROR_NO_MORE_FILES)<br /> {<br /> fFinished = true;<br /> }<br /> }<br /> }<br /> FindClose(hSearch);<br /> for(size_t i = 0; i < tmpList.size(); i++)<br /> filelist.push_back(tmpList[i]);<br /> tmpList.clear();<br />#else<br /> FILE_INFO_ST fileitem;<br /> FILELIST_VECTOR tmpList;<br /> long long filesize;<br /> struct dirent* ent = NULL;<br /> DIR *pDir;<br /> filelist.clear();<br /> pDir = opendir(m_path.c_str());<br /> strcpy(fileitem.filename, "..");<br /> strcpy(fileitem.attribute, "DIR");<br /> filelist.push_back(fileitem);<br /> while ((ent = readdir(pDir))!=NULL)<br /> {<br /> if( strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)<br /> {<br /> continue;<br /> }<br /> struct stat buf;<br /> char tmpFn[MAX_PATH_LENGTH];<br /> memset(tmpFn, 0, MAX_PATH_LENGTH);<br /> strcpy(tmpFn, m_path.c_str());<br /> strcat(tmpFn, "/");<br /> strcat(tmpFn, ent->d_name);<br /> lstat(tmpFn, &buf);<br /> filesize = (unsigned long)buf.st_size;<br /> if((filesize>>50) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024 * 1024 * 1024 * 1024));<br /> sprintf(fileitem.filesize, "%Ild.%Ild PB", filesize>>50, decimal);<br /> }<br /> else if((filesize>>40) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024 * 1024 * 1024));<br /> sprintf(fileitem.filesize, "%Ild.%Ild TB", filesize>>40, decimal);<br /> }<br /> else if((filesize>>30) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024 * 1024));<br /> sprintf(fileitem.filesize, "%Ild.%Ild GB", filesize>>30, decimal);<br /> }<br /> else if((filesize>>20) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024 * 1024));<br /> sprintf(fileitem.filesize, "%Ild.%Ild MB", filesize>>20, decimal);<br /> }<br /> else if((filesize>>10) > 0)<br /> {<br /> long long modnum = filesize % 1024;<br /> long long decimal = (long long)(1.0 * modnum * 100 / (1024));<br /> sprintf(fileitem.filesize, "%Ild.%Ild KB", filesize>>10, decimal);<br /> }<br /> else<br /> sprintf(fileitem.filesize, "%Ild B", filesize);<br /> struct tm* tm = gmtime(&buf.st_mtime);<br /> sprintf(fileitem.lastmodifiedtime, "%02d-%s-%4d %02d:%02d", tm->tm_mday,<br /> MONTH_NAME[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, tm->tm_min);<br /> sprintf(fileitem.filename, ent->d_name);<br /> if(ent->d_type == DT_DIR )<br /> {<br /> sprintf(fileitem.attribute, "%s", "DIR");<br /> filelist.push_back(fileitem);<br /> }<br /> else<br /> {<br /> sprintf(fileitem.attribute, "%s", "---");<br /> tmpList.push_back(fileitem);<br /> }<br /> }<br /> for(size_t i = 0; i < tmpList.size(); i++)<br /> filelist.push_back(tmpList[i]);<br /> tmpList.clear();<br />#endif<br /> return 0;<br />}<br />void IoUtil::GetFileSize( char* filesizeStr )<br />{<br />#if defined WIN32<br /> WIN32_FIND_DATA fileData;<br /> HANDLE hSearch;<br /> long long filesize;<br /> ///////<br /> hSearch = FindFirstFile( m_path.c_str(), &fileData );<br /> if(hSearch == INVALID_HANDLE_VALUE)<br /> return ;<br /> filesize = fileData.nFileSizeHigh;<br /> filesize = filesize << 32;<br /> filesize = filesize + fileData.nFileSizeLow;<br /> sprintf(filesizeStr, "%I64d", filesize);<br /> FindClose(hSearch);<br />#else<br /> struct stat buf;<br /> stat(m_path.c_str(), &buf);<br /> sprintf(filesizeStr, "%lld", buf.st_size);<br />#endif<br />}<br />bool IoUtil::SendFile( SOCKET socket, long long seekpos )<br />{<br />#if defined WIN32<br /> char buffer[1025];<br /> DWORD dwRead;<br /> HANDLE hFile = NULL;<br /> for(int i = 0; i < 20; i++)<br /> {<br /> hFile = ::CreateFile(m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);<br /> if(hFile)<br /> break;<br /> Sleep(200);<br /> }<br /> if(!hFile)<br /> return false;<br /> else<br /> {<br /> LARGE_INTEGER lint ;<br /> lint.QuadPart = seekpos;<br /> SetFilePointer(hFile, lint.LowPart, &lint.HighPart, FILE_BEGIN);<br /> while(1)<br /> {<br /> dwRead = 0;<br /> bool bResult = ::ReadFile(hFile, buffer, 1024, &dwRead, NULL);<br /> if(!bResult)<br /> break;<br /> //end of file<br /> if((bResult) && (dwRead == 0))<br /> break;<br /> int nSend = Send(socket, buffer, dwRead);<br /> if(nSend < 0)<br /> break;<br /> }<br /> CloseHandle(hFile);<br /> return true;<br /> }<br />#else<br /> char buffer[1025];<br /> int dwRead;<br /> FILE* hFile = NULL;<br /> for(int i = 0; i < 20; i++)<br /> {<br /> hFile = fopen(m_path.c_str(), "rb");<br /> if(hFile)<br /> break;<br /> usleep(200000);<br /> }<br /> if(!hFile)<br /> return false;<br /> else<br /> {<br /> while(!feof(hFile))<br /> {<br /> dwRead = 0;<br /> dwRead = fread(buffer, sizeof(char), 1024, hFile);<br /> //end of file<br /> int nSend = Send(socket, buffer, dwRead);<br /> if(nSend < 0)<br /> break;<br /> }<br /> fclose(hFile);<br /> return true;<br /> }<br />#endif<br />}<br />int IoUtil::Send( SOCKET socket, const char* buffer, UINT len )<br />{<br /> long already_time = 0;<br /> fd_set fdset;<br /> struct timeval timeout;<br /> timeout.tv_sec = SELECT_WAIT_TIME;<br /> timeout.tv_usec = 0;<br /> size_t nSend = 0;<br /> size_t tLen = 0;<br /> while(1)<br /> {<br /> FD_ZERO(&fdset);<br /> FD_SET(socket, &fdset);<br /> int ret = select(socket + 1, NULL, &fdset, NULL, &timeout);<br /> switch(ret)<br /> {<br /> case 1:<br /> already_time = 0;<br /> tLen = send(socket, buffer, len - nSend, 0);<br /> nSend += tLen;<br /> if(nSend == len)<br /> return SOCKET_SENDRECV_OK;<br /> break;<br /> case 0:<br /> already_time += SELECT_WAIT_TIME;<br /> if(already_time >= MAX_WAIT_TIME_FOR_SENDRECV)<br /> {<br /> close(socket);<br /> return SOCKET_SENDRECV_TIMEOUT;<br /> }<br /> break;<br /> default:<br /> return SOCKET_SENDRECV_ERROR;<br /> }<br /> }<br />}<br />

 

 

 

 

另外附上socket相關程式在windows和linux下有所區別的地方:

 

1)標頭檔 
windows下winsock.h/winsock2.h 
linux下sys/socket.h 
錯誤處理:errno.h 

2)初始化 
windows下需要用WSAStartup 
linux下不需要 

3)關閉socket 
windows下closesocket(...) 
linux下close(...) 

4)類型 
windows下SOCKET 
linux下int 
如用到的一些宏: 
#ifdef WIN32 
typedef int socklen_t; 
typedef int ssize_t; 
#endif 

#ifdef __LINUX__ 
typedef int SOCKET; 
typedef unsigned char BYTE; 
typedef unsigned long DWORD; 
#define FALSE 0 
#define SOCKET_ERROR (-1) 
#endif 

5)擷取錯誤碼 
windows下getlasterror()/WSAGetLastError() 
linux下errno變數 

6)設定非阻塞 
windows下ioctlsocket() 
linux下fcntl() <fcntl.h> 

7)send函數最後一個參數 
windows下一般設定為0 
linux下最好設定為MSG_NOSIGNAL,如果不設定,在發送出錯後有可 能會導致程式退出。 

8)毫秒級時間擷取 
windows下GetTickCount() 
linux下gettimeofday() 

3、多線程 
多線程: (win)process.h --〉(linux)pthread.h 
_beginthread --> pthread_create 
_endthread --> pthread_exit

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.