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

📄 netmanager.cpp~

📁 查看局域网的信息,类似网上邻居的功能,例如查看哪台计算机在线等
💻 CPP~
📖 第 1 页 / 共 2 页
字号:
/*    netmanager.cpp * *    Copyright (c) 2000, Alexander Neundorf *    neundorf@kde.org * *    You may distribute under the terms of the GNU General Public *    License as specified in the COPYING file. * *    This program is distributed in the hope that it will be useful, *    but WITHOUT ANY WARRANTY; without even the implied warranty of *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *    GNU General Public License for more details. * */#include "config.h"#include "netmanager.h"#include "lisadefines.h"#include <iostream.h>#include <unistd.h>#include <sys/un.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <strings.h>#include <errno.h>#ifndef AF_LOCAL#define AF_LOCAL AF_UNIX#endif#include "getdebug.h"#define getDebug() getDebug()<<procId//#define getDebug() cerr<<procIdNetManager::NetManager(int& rawSocketFD, int portToUse, MyString configFile, int configStyle, int strictMode):NetScanner(rawSocketFD,strictMode)//,validator(),m_listenFD(-1),m_bcFD(-1),m_basePort(portToUse),m_pipeFD(-1),m_receiveBuffer(0),m_receivedBytes(0),m_childPid(0),m_lastUpdate(0),m_isInformed(0),m_isBeingScanned(0),m_firstRun(1),m_serverServer(0),m_servedThisPeriod(0),m_serveCount(0),m_refreshTime(60),m_initialRefreshTime(60),m_increasedRefreshTime(0),m_broadcastAddress(0),m_extraConfigFile(configFile),m_configStyle(configStyle),m_usedConfigFileName(""){   getDebug()<<"NetManager::NetManager"<<endl;   m_startedAt=time(0);};NetManager::~NetManager(){   getDebug()<<"netknife destructor ..."<<endl;   if (m_receiveBuffer!=0) delete [] m_receiveBuffer;   ::close(m_listenFD);   ::close(m_bcFD);};void NetManager::readConfig(){   m_usedConfigFileName=getConfigFileName();   if (m_usedConfigFileName.isEmpty())   {      cout<<"configfile not found"<<endl;      cout<<"use the command line option --help and \ntake a look at the README for more information"<<endl;      exit(1);   };   Config config(m_usedConfigFileName);   NetManager::configure(config);   NetScanner::configure(config);   validator.configure(config);   //after reading the new configuration we should really update   m_lastUpdate=0;};void NetManager::configure(Config& config){   m_refreshTime=config.getEntry("UpdatePeriod",300);   MyString tmp=stripWhiteSpace(config.getEntry("BroadcastNetwork","0.0.0.0/255.255.255.255;"));   tmp=tmp+",";   getDebug()<<"NetManager::readConfig: "<<tmp<<endl;   MyString netAddressStr=tmp.left(tmp.find('/'));   tmp=tmp.mid(tmp.find('/')+1);   tmp=tmp.left(tmp.find(','));   getDebug()<<"NetManager::readConfig: broadcastNet "<<netAddressStr<<" with mask "<<tmp<<endl;   int netMask=inet_addr(tmp.c_str());   int netAddress=inet_addr(netAddressStr.c_str());   m_broadcastAddress= netAddress | (~netMask);   getDebug()<<"NetManager::readConfig: net "<<ios::hex<<netAddress<<" with mask "<<netMask<<" gives "<<m_broadcastAddress<<endl;      //maybe this way we can avoid that all servers on the net send   //their requests synchronously, since now the refreshtime isn't   //always the eact value of m_refreshTime, but differs always slightly   if ((m_refreshTime%SELECT_TIMEOUT)==0) m_refreshTime+=2;   //some limits from half a minute to half an hour   if (m_refreshTime<30) m_refreshTime=30;   if (m_refreshTime>1800) m_refreshTime=1800;   m_initialRefreshTime=m_refreshTime;};int NetManager::prepare(){   getDebug()<<"NetManager::prepare"<<endl;   ::close(m_listenFD);   ::close(m_bcFD);   int result(0);   if (m_strictMode)   {      m_listenFD=::socket(AF_LOCAL, SOCK_STREAM, 0);      //m_listenFD=::socket(AF_LOCAL, SOCK_STREAM, IPPROTO_TCP);      MyString socketName("/tmp/resLisa-");      socketName+=getenv("LOGNAME");      ::unlink(socketName.data());      sockaddr_un serverAddr;      bzero((char*)&serverAddr, sizeof(serverAddr));      serverAddr.sun_family      = AF_LOCAL;      strcpy(serverAddr.sun_path,socketName.data());      ::bind(m_listenFD,(sockaddr*) &serverAddr,sizeof(serverAddr));   }   else   {      //create a listening port and listen      m_listenFD = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);      sockaddr_in serverAddress;      bzero((char*)&serverAddress, sizeof(serverAddress));      serverAddress.sin_family      = AF_INET;      serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);      serverAddress.sin_port        = htons(m_basePort);      int on(1);      result=setsockopt(m_listenFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));      if (result!=0)      {         cout<<"NetManager::prepare: setsockopt(SO_REUSEADDR) failed"<<endl;         return 0;      };      result=::bind(m_listenFD, (struct sockaddr *) &serverAddress, sizeof(serverAddress));      if (result!=0)      {         cout<<"NetManager::prepare: bind (TCP) failed"<<endl;         return 0;      };   };   result=::listen(m_listenFD, 32);   if (result!=0)   {      cout<<"NetManager::prepare: listen failed"<<endl;      return 0;   };   getDebug()<<"NetManager::prepare: listening on port "<<m_basePort<<"..."<<endl;   return 1;};void NetManager::generateFDset(fd_set *tmpFDs){   getDebug()<<"NetManager::generateFDset"<<endl;      FD_ZERO(tmpFDs);   FD_SET(m_listenFD,tmpFDs);   getDebug()<<"NetManager::generateFDset: adding listen FD="<<m_listenFD<<endl;   for (Client* tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())      if (tmpClient->fd()!=-1)      {         getDebug()<<"NetManager::generateFDset: adding client FD="<<tmpClient->fd()<<endl;         FD_SET(tmpClient->fd(),tmpFDs);      };   if (m_pipeFD!=-1)   {      getDebug()<<"NetManager::generateFDset: adding pipeFD="<<m_pipeFD<<endl;      FD_SET(m_pipeFD,tmpFDs);   };   if ((m_bcFD!=-1) && (!m_strictMode))   {      getDebug()<<"NetManager::generateFDset: adding m_bcFD="<<m_bcFD<<endl;      FD_SET(m_bcFD,tmpFDs);   };};int NetManager::waitForSomethingToHappen(fd_set *tmpFDs){   getDebug()<<"NetManager::waitForSomethingToHappen for 10 seconds"<<endl;   if (m_firstRun)   {      tv.tv_sec = 1;      m_firstRun=0;   }   else      tv.tv_sec = SELECT_TIMEOUT;   tv.tv_usec = 0;   //generateFDset(tmpFDs);   int result=select(getMaxFD(),tmpFDs,0,0,&tv);   if (result>0) return 1;   else return 0;};int NetManager::getMaxFD(){   int maxFD(m_listenFD);   for (Client* tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())      if (tmpClient->fd()>maxFD) maxFD=tmpClient->fd();   if (m_pipeFD>maxFD) maxFD=m_pipeFD;   if (m_bcFD>maxFD) maxFD=m_bcFD;   getDebug()<<"NetManager::getMaxFD()="<<maxFD+1<<endl;   return maxFD+1;};int fileReadable(const MyString& filename){   FILE *file=::fopen(filename.data(), "r");   if (file==0)      return 0;   fclose(file);   return 1;};MyString NetManager::getConfigFileName(){   MyString tmpBase(CONFIGFILEBASENAME);   if (m_strictMode)      tmpBase=STRICTCONFIGFILEBASENAME;   if (!m_extraConfigFile.isEmpty())      m_configStyle=EXTRACONFIGSTYLE;   MyString tmpFilename;   if (m_configStyle==EXTRACONFIGSTYLE)   {      tmpFilename=m_extraConfigFile;      if (fileReadable(tmpFilename))         return tmpFilename;      return "";   }   else if (m_configStyle==UNIXCONFIGSTYLE)   {      tmpFilename=getenv("HOME");      tmpFilename+=MyString("/.")+tmpBase;      if (fileReadable(tmpFilename))         return tmpFilename;      tmpFilename="/etc/";      tmpFilename+=tmpBase;      if (fileReadable(tmpFilename))         return tmpFilename;      return "";   }   else if (m_configStyle==KDE1CONFIGSTYLE)   {      tmpFilename=getenv("HOME");      tmpFilename+=MyString("/.kde/share/config/")+tmpBase;      if (fileReadable(tmpFilename))         return tmpFilename;      tmpFilename=getenv("KDEDIR");      tmpFilename+=MyString("/share/config/")+tmpBase;      if (fileReadable(tmpFilename))         return tmpFilename;      return "";   }   else if (m_configStyle==KDE2CONFIGSTYLE)   {      FILE *kdeConfig=popen("kde-config --path config","r");      if (kdeConfig==0)      {         cout<<"could not execute kde-config, check your KDE 2 installation\n"<<endl;         return "";      };      //this should be large enough      char buf[4*1024];      memset(buf,0,4*1024);      fgets(buf,4*1024-1,kdeConfig);      pclose(kdeConfig);      int length=strlen(buf);      if (buf[length-1]=='\n') buf[length-1]='\0';      MyString kdeDirs(buf);      while (kdeDirs.contains(':'))      {         MyString nextDir=kdeDirs.left(kdeDirs.find(':'));         kdeDirs=kdeDirs.mid(kdeDirs.find(':')+1);         nextDir=nextDir+tmpBase;         getDebug()<<"trying to open "<<nextDir<<endl;         if (fileReadable(nextDir))            return nextDir;      };      kdeDirs=kdeDirs+tmpBase;      getDebug()<<"trying to open "<<kdeDirs<<endl;      if (fileReadable(kdeDirs))         return kdeDirs;      return "";   }   return "";};int NetManager::run(){   int continueMainLoop(1);   //not forever	while(continueMainLoop)   {      getDebug()<<"\nTCPServer::run: next loop: "<<clients.size()<<" clients"<<endl;      fd_set tmpFDs;      generateFDset(&tmpFDs);      int result=waitForSomethingToHappen(&tmpFDs);      getDebug()<<"NetManager::run: something happened..."<<endl;      //timeout      if (result==0)      {         getDebug()<<"NetManager::run: serverServer=="<<m_serverServer<<endl;         getDebug()<<"NetManager::run: scanning after timeout"<<endl;         scan();      }      else      {         //a new connection ?         if (FD_ISSET(m_listenFD,&tmpFDs))         {            getDebug()<<"NetManager::run: on m_listenFD"<<endl;            struct sockaddr_in clientAddress;            ksize_t clilen(sizeof(clientAddress));            bzero((char*)&clientAddress, clilen);            int connectionFD=::accept(m_listenFD,(struct sockaddr *) &clientAddress, &clilen);            if ((validator.isValid(clientAddress.sin_addr.s_addr)) || (m_strictMode))            {               getDebug()<<"NetManager::run: adding client"<<endl;               addClient(connectionFD);               m_servedThisPeriod=1;               m_refreshTime=m_initialRefreshTime;               m_increasedRefreshTime=0;            }            else            {               getDebug()<<"NetManager::run: kicking client"<<endl;               ::close(connectionFD);            };         };         checkClientsAndPipes(&tmpFDs);      };      serveAndClean();   };      return 1;};void NetManager::addClient(int socketFD){   getDebug()<<"NetManager::addClient on FD="<<socketFD<<endl;   if (socketFD==-1) return;   Client c(this,socketFD,0);   clients.append(c);};void NetManager::checkClientsAndPipes(fd_set *tmpFDs){   getDebug()<<"NetManager::checkClientsAndPipes()"<<endl;   //actually the clients should not send anything   for (Client *tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())   {      getDebug()<<"NetManager::checkClientsAndPipes: checking client"<<endl;      if (FD_ISSET(tmpClient->fd(),tmpFDs))      {         getDebug()<<"NetManager::checkClientsAndPipes: client sent something"<<endl;         tmpClient->read();      };   };   //now check wether we received a broadcast   //m_bcFD should always be -1 in strictMode   if ((m_bcFD!=-1) && (!m_strictMode))   {      getDebug()<<"NetManager::checkClientsAndPipe: checking bcFD"<<endl;      //yes !      if (FD_ISSET(m_bcFD,tmpFDs))         answerBroadcast();   };   //read the stuff from the forked pipe   if (m_pipeFD!=-1)   {      getDebug()<<"NetManager::checkClientsAndPipe: checking pipe"<<endl;      if (FD_ISSET(m_pipeFD,tmpFDs))      {         getDebug()<<"NetManager::checkClientsAndPipes: pipe sent something"<<endl;         int result=readDataFromFD(m_pipeFD);         if (result!=1)         {            ::close(m_pipeFD);                        //can I really be 100% sure that the child will quit very soon ?            //::waitpid(m_childPid,0,0);            //I better wait for a short moment and then continue            //it's better to have possibly a zombie than a blocking server IMO            timeval tv;            tv.tv_sec=0;            tv.tv_usec=5*10*1000;//0.05 sec            ::select(0,0,0,0,&tv);            ::waitpid(m_childPid,0,WNOHANG);            m_pipeFD=-1;            getDebug()<<"NetManager::checkClientsAndPipes: everything read from pipe from proc "<<m_childPid<<endl;            processScanResults();         };      };   };};void NetManager::answerBroadcast(){   //actually we should never get here in strictMode   if (m_strictMode) return;      //this one is called only in checkClientsAndPipes()   //if we are sure that we received something on m_bcFD   //so we don't need to check here again      getDebug()<<"NetManager::answerBroadcast: received BC"<<endl;   struct sockaddr_in sAddr;   socklen_t length(sizeof(sockaddr_in));   char buf[1024];   int result=recvfrom(m_bcFD, (void*)buf, 1024, 0, (sockaddr*)&sAddr,&length);   getDebug()<<"NetManager::answerBroadcast: received succesfully"<<endl;   //did recvfrom() succeed ?   //our frame is exactly MYFRAMELENGTH bytes big, if the received one has a different size,   //it must be something different   if (result!=MYFRAMELENGTH) return;   //if it has the correct size, it also must have the correct identifier   MyFrameType *frame=(MyFrameType*)(void*)buf;   if ((ntohl(frame->id)!=MY_ID) ||       ((ntohl(frame->unused1)==getpid()) && (ntohl(frame->unused2)==m_startedAt)))   {      getDebug()<<"NetManager::answerBroadcast: must be the same machine"<<endl;      return;   };   //getDebug()<<"received "<<ntohl(buf[0])<<" from "<<inet_ntoa(sAddr.sin_addr)<<hex<<" ";   //getDebug()<<sAddr.sin_addr.s_addr<<" "<<ntohl(sAddr.sin_addr.s_addr)<<dec<<endl;   //will we answer this request ?   if (!validator.isValid(sAddr.sin_addr.s_addr))   {      getDebug()<<"NetManager::answerBroadcast: invalid sender"<<endl;      return;   };   //create the answering socket   int answerFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);   if (answerFD==-1)   {      getDebug()<<"NetManager::answerBroadcast: could not create answering socket"<<endl;      return;   };      sAddr.sin_family=AF_INET;   sAddr.sin_port=htons(m_basePort+1);   MyFrameType answerFrame;   answerFrame.id=htonl(MY_ID);   answerFrame.unused1=0;   answerFrame.unused2=0;   //don't care about the result   getDebug()<<"NetManager::answerBroadcast: sending answer"<<endl;   result=::sendto(answerFD,(void*)&answerFrame,sizeof(answerFrame),0,(sockaddr*)&sAddr,length);   getDebug()<<"sent "<<result<<" byte using sendto"<<endl;   ::close(answerFD);   //sent answer};void NetManager::serveAndClean(){

⌨️ 快捷键说明

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