win32socketpeer.cpp
来自「这是VCF框架的代码」· C++ 代码 · 共 568 行
CPP
568 行
//Win32SocketPeer.cpp/*Copyright 2000-2004 The VCF Project.Please see License.txt in the top level directorywhere you installed the VCF.*/#include <winsock2.h> //makes sure to link with Ws2_32.lib#include "vcf/NetworkKit/NetworkKit.h"#include "vcf/NetworkKit/NetworkKitPrivate.h"using namespace VCF;using namespace VCFNet;bool Win32SocketPeer::WinSockStarted = false;struct MemStruct{ int size; char* data;};Win32SocketPeer::Win32SocketPeer( Socket* socket, const String& host, const int& port ) { socket_ = socket; host_ = host; port_ = port; sock_ = 0; memset( &sin_, 0, sizeof(sin_) ); if ( false == Win32SocketPeer::WinSockStarted ) { Win32SocketPeer::startup(); }}Win32SocketPeer::Win32SocketPeer( Socket* socket, const int& socketPeerID, const VCF::String& host, const int& port ){ socket_ = socket; host_ = host; port_ = port; sock_ = socketPeerID; memset( &sin_, 0, sizeof(sin_) ); if ( false == Win32SocketPeer::WinSockStarted ) { Win32SocketPeer::startup(); }}Win32SocketPeer::~Win32SocketPeer(){ std::vector<Socket*>::iterator it = connectedClients_.begin(); while ( it != connectedClients_.end() ) { Socket* so = *it; printf( "deleting %x\n", so ); delete so; it++; } if ( 0 != sock_ ) { closesocket(sock_); sock_ = 0; } connectedClients_.clear(); disconnectedClients_.clear(); socket_ = NULL;}SocketState Win32SocketPeer::stopListening(){ SocketState result = SOCKET_CONNECT_ERROR; return result;}SocketState Win32SocketPeer::startListening(){ if ( SOCKET_CLOSED != this->socket_->getState() ){ return SOCKET_ALREADY_LISTENING_ERROR; } //printf("starting to listen for incoming sockets...\n"); int length = 0; int msgsock = 0; /** *we want to create a socket in two different *ways depending on how the Socket::isServer_ is set *if true then bind and listen *otherwise connect ? */ //Create a socket if neccessary if ( sock_ <= 0 ) { sock_ = ::socket(AF_INET,SOCK_STREAM,0); if (sock_ < 0) { sock_ = 0; return SOCKET_CANT_OPEN_SOCKET; } } if ( true == this->socket_->isServer() ) { // Initialize the socket's address structure sin_.sin_family = AF_INET; sin_.sin_addr.s_addr = INADDR_ANY; sin_.sin_port = htons((short)port_); // Assign an address to this socket int bindErr = bind( sock_, (sockaddr*)&sin_, sizeof(sin_) ); if ( bindErr < 0) { closesocket( sock_ ); sock_ = 0; return SOCKET_BIND_FAILED; } //Prepare the socket queue for connection requests int listenErr = listen( sock_, 5 ); } else { SocketState state = connectTo( this->host_, this->port_ ); socket_->setState( state ); } return SOCKET_LISTENING;}int Win32SocketPeer::send( const char* bytes, const int& size ){ int result = 0; if ( SOCKET_CLOSED == this->socket_->getState() ){ //connect SocketState state = connectTo( this->host_, this->port_ ); socket_->setState( state ); } result = ::send( sock_, bytes, size, 0 ); if ( -1 == result ) { int i = WSAGetLastError(); } return result;}void Win32SocketPeer::startup() { if ( true == Win32SocketPeer::WinSockStarted ) { return; } WORD wVersionRequested = MAKEWORD(1, 1); WSADATA wsaData; int err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { //throw exception WSACleanup(); //throw SocketException( "Winsock dll load failed." ); } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup(); //throw SocketException( "Winsock version 1.1 not found." ); } Win32SocketPeer::WinSockStarted = true;}SocketState Win32SocketPeer::connectTo( const String& hostName, const int& port ){ SocketState result = SOCKET_CONNECT_ERROR; host_ = hostName; const char* tmpHostName = hostName.ansi_c_str(); struct hostent *hp; if ( 0 != sock_ ){ //attempt to close the previous connection closesocket( sock_ ); sock_ = 0; } port_ = port; sock_ = socket (AF_INET, SOCK_STREAM, 0); if ( sock_ < 0 ) { return SOCKET_CANT_OPEN_SOCKET; } // Initialize the socket address to the server's address. memset( &sin_, 0, sizeof(sin_) ); sin_.sin_family = AF_INET; hp = gethostbyname( tmpHostName ); //to get host address if (hp == NULL) { return SOCKET_CANT_OPEN_SOCKET; } memcpy( &(sin_.sin_addr.s_addr), hp->h_addr, hp->h_length ); sin_.sin_port = htons((short)port_); // Connect to the server. int connectErr = connect(sock_, (sockaddr*)&sin_,sizeof(sin_)); if ( connectErr < 0) { int i = WSAGetLastError(); closesocket(sock_); return SOCKET_CONNECT_ERROR; } return SOCKET_CONNECTED;}void Win32SocketPeer::setPort( const int& port ){ this->port_ = port; this->socket_->setState( SOCKET_CLOSED ); if ( 0 != sock_ ){ //attempt to close the previous connection closesocket( sock_ ); sock_ = 0; }}int Win32SocketPeer::getPort(){ return port_;}void Win32SocketPeer::setHost( const String& host ){ host_ = host; this->socket_->setState( SOCKET_CLOSED ); if ( 0 != sock_ ){ //attempt to close the previous connection closesocket( sock_ ); sock_ = 0; }}String Win32SocketPeer::getHost(){ return host_;}bool Win32SocketPeer::hasWaitingClients(){ bool result = false; struct timeval timeout ; fd_set fd ; FD_ZERO(&fd); FD_SET ( sock_, &fd) ; timeout.tv_sec = 0 ; timeout.tv_usec = 0 ; int selectResult = SOCKET_ERROR; if ( this->socket_->isServer() ) { selectResult = select( sock_ + 1, &fd, NULL, NULL, &timeout ); } else { selectResult = select( sock_ + 1, NULL, &fd, NULL, &timeout ); } if ( SOCKET_ERROR == selectResult ){ //throw exception } result = ( selectResult > 0 ); if ( result ) { int i = 8; i++; } return result;}Socket* Win32SocketPeer::getClient(){ Socket* result = NULL; if ( true == this->socket_->isServer() ) { int length = 0; int msgsock = 0; //Initialize the socket's address structure sin_.sin_family = AF_INET; sin_.sin_addr.s_addr = INADDR_ANY; sin_.sin_port = htons((short)port_); //StringUtils::trace("Listening for connect requests on port " + StringUtils::toString(port_) + "\n" ); //printf( "Listening for connect requests on port %d\n", port_ ); //Prepare the socket queue for connection requests length = sizeof(sin_); msgsock = accept( sock_, (sockaddr*)&sin_, &length ); if (msgsock != SOCKET_ERROR) { result = new Socket( msgsock, host_, port_ ); this->connectedClients_.push_back( result ); } else { //StringUtils::trace("Accept() failed on sock_ = " + StringUtils::toString((int)sock_) + "\n" ); //printf("Accept() failed on sock_ = %d\n", sock_ ); } //StringUtils::trace("Connection from host " + host_ + " port: " + StringUtils::toString(port_) + "\n" ); //printf("Connection from host %s port: %d\n", host_.c_str(), port_ ); } else { if ( true == connectedClients_.empty() ) { result = new Socket(sock_, host_, port_ ); this->connectedClients_.push_back( result ); } } return result;}void Win32SocketPeer::readDataFromClient( Socket* client, fd_set* readfd ){ if ( NULL == client ) { return; } int clientSock = client->getSocketPeer()->getSocketPeerID(); if (FD_ISSET (clientSock, readfd)) { //StringUtils::trace( StringUtils::toString(*it) + " sent data...\n" ); //printf( "%d sent data...\n", client->socketID_ ); // this guy sent something char buf[VCFNET_MAX_SOCKET_SIZE]; char* totalDataBuf = NULL; int totalSize = VCFNET_MAX_SOCKET_SIZE; std::vector<MemStruct*> dataList; memset( buf, 0 , VCFNET_MAX_SOCKET_SIZE*sizeof(char) ); //read first chunk of data int recvResult = recv( clientSock, buf, VCFNET_MAX_SOCKET_SIZE, 0 ); switch ( recvResult ) { case 0 : { //printf( "client closed connection - fire event\n" ); //client closed connection - fire event SocketEvent event( socket_, client ); this->socket_->ClientDisconnected.fireEvent( &event ); disconnectedClients_.push_back( client ); } break; case SOCKET_ERROR : { //socket error throw exception ???? if ( false == this->socket_->isServer() ) { //possible problem - perhaps the server int err = WSAGetLastError(); switch ( err ) { case WSAECONNRESET : { SocketEvent event( socket_, client ); this->socket_->ClientDisconnected.fireEvent( &event ); disconnectedClients_.push_back( client ); } break; } } } break; default : { // NK: First add data received so far into dataList. MemStruct* memStruct = new MemStruct; memStruct->data = new char[recvResult]; memset( memStruct->data, 0, recvResult*sizeof(char) ); memStruct->size = recvResult; memcpy(memStruct->data, buf, recvResult ); dataList.push_back( memStruct ); totalSize = recvResult; //check to see if more data is still out there u_long res = 0; ioctlsocket( clientSock, FIONREAD, &res ); char* tmp = NULL; if ( res > 0 ){ while ( res > 0 ){ //continue to pull data MemStruct* memStruct = new MemStruct; memStruct->data = new char[res]; memset( memStruct->data, 0, res*sizeof(char) ); memStruct->size = res; recvResult = recv( clientSock, memStruct->data, res, 0 ); if ( recvResult != SOCKET_ERROR ){ dataList.push_back( memStruct ); totalSize += res; ioctlsocket( clientSock, FIONREAD, &res ); } else { res = 0; } } } if ( ! dataList.empty() ){ totalDataBuf = new char[totalSize]; memset( totalDataBuf, 0, totalSize*sizeof(char) ); char* tmpBuf = totalDataBuf; int insertData = 0; std::vector<MemStruct*>::iterator dataIt = dataList.begin(); while ( dataIt != dataList.end() ){ MemStruct* memStruct = (*dataIt); tmp = memStruct->data; memcpy( tmpBuf, tmp, memStruct->size ); tmpBuf += memStruct->size; delete [] memStruct->data; memStruct->data = NULL; delete memStruct; memStruct = NULL; dataIt++; } } else { totalDataBuf = buf; } //finished reading - fire event SocketEvent event( socket_, client, totalDataBuf, totalSize ); this->socket_->DataReceived.fireEvent( &event ); } break; } }}void Win32SocketPeer::checkForPendingData( const int& waitAndBlock ){ //printf( "Starting checkForPendingData()...\n" ); if ( !connectedClients_.empty() ){ //StringUtils::trace( "checkForPendingData() has clients - looping...\n" ); //printf( "checkForPendingData() has clients - looping...\n" ); std::vector<Socket*>::iterator it = connectedClients_.begin(); fd_set readfd; FD_ZERO(&readfd); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; int maxSock = 0; while ( it != connectedClients_.end() ){ Socket* so = *it; int sockID = so->getSocketPeer()->getSocketPeerID(); FD_SET ( sockID, &readfd) ; if ( sockID > maxSock ){ maxSock = sockID; } it++; } //printf( "maxSock = %d\n", maxSock ); struct timeval* timeoutVal = NULL; if ( (VCFNET_ASYNCHRONOUSWAIT == waitAndBlock) ) { timeoutVal = &timeout; } else if ( waitAndBlock > 0 ) { timeout.tv_sec = waitAndBlock / 1000; //waitAndBlock is in milliseconds timeoutVal = &timeout; } int i = select( maxSock + 1, &readfd, NULL, NULL, timeoutVal); //printf( "select( %d, ... ), returned %d\n", maxSock + 1, i ); if ( (SOCKET_ERROR != i) && ( i > 0 ) ){ //no errors, and 1 or more sockets have data it = connectedClients_.begin(); while ( it != connectedClients_.end() ){ readDataFromClient( *it, &readfd ); //printf( "readDataFromClient( so->socketID_=%d)\n", (*it)->socketID_ ); it++; } it = this->disconnectedClients_.begin(); while ( it != disconnectedClients_.end() ) { Socket* so = *it; std::vector<Socket*>::iterator found = std::find( connectedClients_.begin(), connectedClients_.end(), so ); if ( found != connectedClients_.end() ) { connectedClients_.erase( found ); delete so; so = NULL; } it++; } disconnectedClients_.clear(); } else { //printf( "select() failed - returned %d\n\terror was : %s", i, getWSAErrorString( WSAGetLastError() ) ); } } //printf( "finished checkForPendingData()...\n" );}VCF::String Win32SocketPeer::getLocalMachineName(){ Win32SocketPeer::startup(); VCF::String result = ""; struct hostent *hp; hp = gethostbyname( "localhost" ); if ( NULL != hp ) { result = hp->h_name; } return result;}int Win32SocketPeer::getSocketPeerID(){ return this->sock_;}/***CVS Log info*$Log$*Revision 1.3 2005/07/09 23:15:17 ddiego*merging in changes from devmain-0-6-7 branch.**Revision 1.2.4.1 2005/04/09 17:21:40 marcelloptr*bugfix [ 1179853 ] memory fixes around memset. Documentation. DocumentManager::saveAs and DocumentManager::reload**Revision 1.2 2004/08/07 02:49:19 ddiego*merged in the devmain-0-6-5 branch to stable**Revision 1.1.2.2 2004/04/29 04:12:57 marcelloptr*reformatting of source files: macros and csvlog and copyright sections**Revision 1.1.2.1 2004/04/28 03:45:49 ddiego*migration towards new directory structure**Revision 1.15.8.1 2004/04/26 16:43:34 ddiego*checked in some minor fixes to some of the other*libraries due to switch over to unicode**Revision 1.15 2003/05/17 20:37:39 ddiego*this is the checkin for the 0.6.1 release - represents the merge over from*the devmain-0-6-0 branch plus a few minor bug fixes**Revision 1.14.2.1 2003/03/12 03:12:42 ddiego*switched all member variable that used the "m_"<name> prefix to* <name>"_" suffix nameing standard.*Also changed all vcf builder files to accomadate this.*Changes were made to the Stream classes to NOT multiple inheritance and to*be a little more correct. Changes include breaking the FileStream into two*distinct classes, one for input and one for output.**Revision 1.14 2003/02/26 04:30:51 ddiego*merge of code in the devmain-0-5-9 branch into the current tree.*most additions are in the area of the current linux port, but the major*addition to this release is the addition of a Condition class (currently*still under development) and the change over to using the Delegate class*exclusively from the older event handler macros.**Revision 1.13.14.1 2003/01/08 00:19:54 marcelloptr*mispellings and newlines at the end of all source files**Revision 1.13 2002/05/09 03:10:45 ddiego*merged over code from development branch devmain-0-5-1a into the main CVS trunk**Revision 1.12.4.1 2002/03/22 17:32:31 zzack*changed to new include style**Revision 1.12 2002/02/27 04:16:12 ddiego*add sub items to TreeItem class for teh tree list control*added fixes to the RemoteObject stuff**Revision 1.11 2002/01/24 01:46:49 ddiego*added a cvs "log" comment to the top of all files in vcf/src and vcf/include*to facilitate change tracking**/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?