#include <NetTcp.h>
Public Member Functions | |
CTcpConnection (CNetTcp *NetTcp, bool ServerInstance) | |
Construtor da classe, usado para criar um novo objeto. | |
~CTcpConnection () | |
Destrutor da classe, usado para remover um objeto criado. | |
RioResult | Initialize (int IP, int Port, int Socket, int HostIP, time_t ConnectionTimeOut, CLogRotation *LogRotation) |
Funcao para inicializar a nova conexao TCP criada. | |
RioResult | EnableConnection (void) |
Funcao para habilitar o uso da conexao TCP (a thread criada na funcao Initialize acima ficara bloqueada em uma variavel de condicao ate esta funcao ser chamada. | |
RioResult | CancelConnection (void) |
Funcao para abortar a execucao da thread (a thread nao deletara o objeto neste caso). | |
RioResult | PutSendData (char *Data, unsigned int DataSize, void *Param, unsigned int *SendDataSize) |
Funcao para inserir um conjunto de dados a serem enviados posteriormente pelo socket da conexao TCP. | |
RioResult | GetIpAndPort (int *IP, int *Port) |
Funcao para obter o IP, a porta associado a conexao TCP do objeto (usado para colocar o objeto na hash de conexoes). | |
Private Member Functions | |
RioResult | GetSendData (char **Data, unsigned int *DataSize, void **Param) |
Funcao para obter um conjunto de dados a serem enviados do objeto da classe. | |
RioResult | ReceiveStreamData (char **Data, unsigned int *DataSize) |
Funcao para receber dados de uma conexao TCP associada ao stream. | |
RioResult | SendStreamData (unsigned int *DataSize, void **Param) |
Funcao para enviar o primeiro bloco de dados pendente em um stream TCP. | |
bool | WaitEnableConnection (void) |
Funcao para esperar ate que a funcao EnableConnection. | |
bool | TcpNetMgrThread (void) |
Funcao que efetivamente executa o codigo da thread de gerenciamento da reda, chamada pela funcao ReceiveThreadEp (esta funcao e usada para facilitar o acesso aos campos do objeto). | |
Static Private Member Functions | |
static void * | TcpNetMgrThreadEp (void *ThreadParam) |
Funcao que trata da execucao do codigo da thread de gerenciamento das conexoes TCP ativas. | |
Private Attributes | |
CNetTcp * | m_NetTcp |
bool | m_Initialized |
bool | m_ServerInstance |
CLogRotation * | m_LogRotation |
int | m_IP |
int | m_Port |
int | m_Socket |
time_t | m_LastUseTime |
time_t | m_ConnectionTimeOut |
TSendQueue | m_SendQueue |
bool | m_isClosingSocket |
pthread_t | m_TcpNetMgrThreadId |
pthread_mutex_t | m_Mutex |
pthread_cond_t | m_Cond |
bool | m_isAborted |
bool | m_SentSignal |
int | m_PollSocket |
struct sockaddr_in | m_PollSocketAddr |
Definition at line 199 of file NetTcp.h.
CTcpConnection::CTcpConnection | ( | CNetTcp * | NetTcp, | |
bool | ServerInstance | |||
) |
Construtor da classe, usado para criar um novo objeto.
NetTcp | ponteiro para o objeto da classe CNetTcp que criou a conexao TCP. | |
ServerInstance | se a conexao esta associada a um cliente ou a um servidor |
Definition at line 66 of file NetTcp.cpp.
00067 { 00068 // Atribui o ponteiro para a classe de gerenciamento do TCP. 00069 m_NetTcp = NetTcp; 00070 00071 #ifdef RIO_DEBUG1 00072 TCPCONNECTIONLOG << "[CTcpConnection - Construtor] Start" << endl; 00073 #endif 00074 00075 // Inicializa as variaveis da classe. 00076 m_NetTcp = NetTcp; 00077 m_ServerInstance = ServerInstance; 00078 m_IP = 0; 00079 m_Port = 0; 00080 m_Socket = 0; 00081 m_LastUseTime = 0; 00082 m_isClosingSocket = false; 00083 m_LogRotation = NULL; 00084 m_isAborted = false; 00085 m_ConnectionTimeOut = 0; 00086 m_SentSignal = false; 00087 m_PollSocket = 0; 00088 memset( &m_PollSocketAddr, 0, sizeof( m_PollSocketAddr ) ); 00089 #ifdef RIO_DEBUG2 00090 m_ReceiveCount = 0; 00091 m_SendCount = 0; 00092 #endif 00093 // m_SendQueue nao precisa ser inicializada 00094 00095 // Define que o objeto ainda nao foi inicializado. 00096 m_Initialized = false; 00097 00098 // Inicializa o mutex da classe, usado para garantir o acesso exclusivo 00099 // as variaveis da classe, a variavel de condicao usada para bloquear a 00100 // thread de gerenciamento da rede ate que 00101 pthread_mutex_init( &m_Mutex, NULL ); 00102 pthread_cond_init( &m_Cond, NULL ); 00103 00104 #ifdef RIO_DEBUG1 00105 TCPCONNECTIONLOG << "[CTcpConnection - Construtor] Finish" << endl; 00106 #endif 00107 }
CTcpConnection::~CTcpConnection | ( | ) |
Destrutor da classe, usado para remover um objeto criado.
Definition at line 110 of file NetTcp.cpp.
00111 { 00112 #ifdef RIO_DEBUG1 00113 TCPCONNECTIONLOG << "[CTcpConnection - Destrutor] Start" << endl; 00114 #endif 00115 00116 // Destroi o mutex da classe. 00117 pthread_mutex_destroy( &m_Mutex ); 00118 00119 // Destroi a variavel de condicao da classe usada para bloquear uma thread 00120 // ate o processo inicial de conexao ter sido finalizado. 00121 pthread_cond_destroy( &m_Cond ); 00122 00123 #ifdef RIO_DEBUG1 00124 TCPCONNECTIONLOG << "[CTcpConnection - Destrutor] Finish" << endl; 00125 #endif 00126 }
RioResult CTcpConnection::CancelConnection | ( | void | ) |
Funcao para abortar a execucao da thread (a thread nao deletara o objeto neste caso).
A funcao esperara ate que a thread termine a sua execucao.
Definition at line 1748 of file NetTcp.cpp.
01749 { 01750 #ifdef RIO_DEBUG1 01751 TCPCONNECTIONLOG << "[CTcpConnection - CancelConnection] Start" << endl; 01752 #endif 01753 01754 // Verifica se o objeto da classe ja foi inicializado. 01755 if( !m_Initialized ) 01756 { 01757 #ifdef RIO_DEBUG2 01758 TCPCONNECTIONLOG << "CTcpConnection::CancelConnection o objeto da " 01759 << "classe nao esta inicializado!" << endl; 01760 #endif 01761 01762 #ifdef RIO_DEBUG1 01763 TCPCONNECTIONLOG << "[CTcpConnection - CancelConnection] Finish1" 01764 << endl; 01765 #endif 01766 01767 return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED; 01768 } 01769 01770 // Obtem o lock do objeto. 01771 pthread_mutex_lock( &m_Mutex ); 01772 01773 // Informa que a conexao foi cancelada e que a thread deve finalizar a 01774 // execucao (sem remover o objeto). 01775 m_isAborted = true; 01776 01777 // Sinaliza a variavel de condicao, para desbloquear a thread da conexao 01778 // TCP. 01779 pthread_cond_signal( &m_Cond ); 01780 01781 // Informa que um sinal foi gerado. 01782 m_SentSignal = true; 01783 01784 // Libera o acesso exlusivo ao lock. 01785 pthread_mutex_unlock( &m_Mutex ); 01786 01787 // Espera ate que a thread termine a sua execucao. 01788 pthread_join( m_TcpNetMgrThreadId, NULL ); 01789 01790 #ifdef RIO_DEBUG1 01791 TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Finish2" << endl; 01792 #endif 01793 01794 return S_OK; 01795 }
RioResult CTcpConnection::EnableConnection | ( | void | ) |
Funcao para habilitar o uso da conexao TCP (a thread criada na funcao Initialize acima ficara bloqueada em uma variavel de condicao ate esta funcao ser chamada.
Obs: Esta funcao e usada para evitar que a thread da conexao execute o select antes do processo de inicializacao da conexao ter sido finalizado, o que poderia confundir este processo porque o select poderia incorretamente reportar os dados de inicializacao como dados validos recebidos (ou enviados) do (para o) outro lado.
Definition at line 1704 of file NetTcp.cpp.
01705 { 01706 #ifdef RIO_DEBUG1 01707 TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Start" << endl; 01708 #endif 01709 01710 // Verifica se o objeto da classe ja foi inicializado. 01711 if( !m_Initialized ) 01712 { 01713 #ifdef RIO_DEBUG2 01714 TCPCONNECTIONLOG << "CTcpConnection::EnableConnection o objeto da " 01715 << "classe nao esta inicializado!" << endl; 01716 #endif 01717 01718 #ifdef RIO_DEBUG1 01719 TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Finish1" 01720 << endl; 01721 #endif 01722 01723 return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED; 01724 } 01725 01726 // Obtem o lock do objeto. 01727 pthread_mutex_lock( &m_Mutex ); 01728 01729 // Sinaliza a variavel de condicao, para desbloquear a thread da conexao 01730 // TCP. 01731 pthread_cond_signal( &m_Cond ); 01732 01733 // Informa que um sinal foi gerado. 01734 m_SentSignal = true; 01735 01736 // Libera o acesso exlusivo ao lock. 01737 pthread_mutex_unlock( &m_Mutex ); 01738 01739 #ifdef RIO_DEBUG1 01740 TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Finish2" << endl; 01741 #endif 01742 01743 return S_OK; 01744 }
RioResult CTcpConnection::GetIpAndPort | ( | int * | IP, | |
int * | Port | |||
) |
Funcao para obter o IP, a porta associado a conexao TCP do objeto (usado para colocar o objeto na hash de conexoes).
IP | ponteiro para o endreco onde colocaremos o IP. | |
Port | ponteiro para o endereco onde colocaremos a porta. |
Definition at line 1955 of file NetTcp.cpp.
01956 { 01957 // Verifica se o objeto da classe ja foi inicializado. 01958 if( !m_Initialized ) 01959 { 01960 // Inicializa o IP e a porta com valores invalidos. 01961 *IP = 0; 01962 *Port = 0; 01963 01964 #ifdef RIO_DEBUG2 01965 TCPCONNECTIONLOG << "CTcpConnection::GetIpAndPort o objeto da classe " 01966 << "nao esta inicializado!" << endl; 01967 #endif 01968 01969 #ifdef RIO_DEBUG1 01970 TCPCONNECTIONLOG << "[CTcpConnection - GetIpAndPort] Finish1" << endl; 01971 #endif 01972 01973 return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED; 01974 } 01975 01976 *IP = m_IP; 01977 *Port = m_Port; 01978 01979 #ifdef RIO_DEBUG1 01980 TCPCONNECTIONLOG << "[CTcpConnection - GetIpAndPort] Finish2" << endl; 01981 #endif 01982 01983 return S_OK; 01984 }
RioResult CTcpConnection::GetSendData | ( | char ** | Data, | |
unsigned int * | DataSize, | |||
void ** | Param | |||
) | [private] |
Funcao para obter um conjunto de dados a serem enviados do objeto da classe.
Data | ponteiro para armazenar o endereco do inicio dos dados | |
DataSize | ponteiro para armazenar o tamanho dos dados a serem transferidos. | |
Param | ponteiro para armazenar o parametro void* (passado ao chamarmos a funcao SendData da classe CNetTCP). |
Definition at line 129 of file NetTcp.cpp.
00131 { 00132 #ifdef RIO_DEBUG1 00133 TCPCONNECTIONLOG << "[CTcpConnection - GetSendData] Start" << endl; 00134 #endif 00135 00136 // Obtem o lock do objeto. 00137 pthread_mutex_lock( &m_Mutex ); 00138 00139 // Agora verificamos se existem dados para serem enviados, mas antes 00140 // deveremos verificar se a fila de envio esta vazia. 00141 if( m_SendQueue.empty() ) 00142 { 00143 // Obtem o lock do objeto. 00144 pthread_mutex_unlock( &m_Mutex ); 00145 00146 // Neste caso nao temos dados para enviar (o tratamento do erro sera da 00147 // classe CNetTcp, pois o erro de implementacao esta nesta classe). 00148 #ifdef RIO_DEBUG2 00149 TCPCONNECTIONLOG << "CTcpConnection::GetSendData a fila de envio do " 00150 << "socket com a ID " << m_Socket << " esta vazia!" 00151 << endl; 00152 #endif 00153 00154 *Data = NULL; 00155 *DataSize = 0; 00156 *Param = NULL; 00157 00158 #ifdef RIO_DEBUG1 00159 TCPCONNECTIONLOG << "[CTcpConnection - GetSendData] Finish1" << endl; 00160 #endif 00161 00162 return ERROR_TCPCONNECTION + ERROR_UNEXPECTED; 00163 } 00164 else 00165 { 00166 #ifdef RIO_DEBUG2 00167 TCPCONNECTIONLOG << "CTcpConnection::GetSendData tentando retirar os " 00168 << "dados a serem enviados pelo socket com a ID " 00169 << m_Socket << ". Tamanho da fila e de " 00170 << m_SendQueue.size() << "." << endl; 00171 #endif 00172 00173 // Obtem os dados a serem enviados primeiramente (que estarao no inicio 00174 // da fila) e remove esta entrada da fila. 00175 *Data = m_SendQueue.front().Data; 00176 *DataSize = m_SendQueue.front().DataSize; 00177 *Param = m_SendQueue.front().Param; 00178 // Sera que isso pode gerar um erro? Eu nao tenho certeza. 00179 m_SendQueue.pop(); 00180 00181 #ifdef RIO_DEBUG2 00182 TCPCONNECTIONLOG << "CTcpConnection::GetSendData dados a serem " 00183 << "enviados pelo socket com a ID " << m_Socket 00184 << " retirados com sucesso. Tamanho da fila e agora " 00185 << "de " << m_SendQueue.size() << "." << endl; 00186 #endif 00187 } 00188 00189 // Libera o acesso exlusivo ao lock. 00190 pthread_mutex_unlock( &m_Mutex ); 00191 00192 #ifdef RIO_DEBUG1 00193 TCPCONNECTIONLOG << "[CTcpConnection - GetSendData] Finish2" << endl; 00194 #endif 00195 00196 return S_OK; 00197 }
RioResult CTcpConnection::Initialize | ( | int | IP, | |
int | Port, | |||
int | Socket, | |||
int | HostIP, | |||
time_t | ConnectionTimeOut, | |||
CLogRotation * | LogRotation | |||
) |
Funcao para inicializar a nova conexao TCP criada.
IP | endereco IP associado ao stream. | |
Port | porta associadao ao stream. | |
Socket | socket associado ao stream. | |
HostIP | associado a maquina na qual o objeto foi alocado (usado para criar o socket UDP). | |
ConnectionTimeOut | tempo de timeout da conexao TCP. | |
LogRotation | ponteiro para a classe que gerencia os logs. |
Definition at line 1529 of file NetTcp.cpp.
01532 { 01533 // Atributos da thread de gerenciamento das conexoes TCP. 01534 pthread_attr_t attribTcpNetMgrThread; 01535 // Armazena o endereco do socket usado para desbloquear o select antes de 01536 // obtermos a porta (escolhida aleatoriamente pelo sistema operacional). 01537 struct sockaddr_in TempAddr; 01538 // Armazena o tamanho do endereco do socket usado para desbloquear o select. 01539 socklen_t AddrSize; 01540 01541 #ifdef RIO_DEBUG1 01542 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Start" << endl; 01543 #endif 01544 01545 // Verifica se o objeto da classe ja foi inicializado. 01546 if( m_Initialized ) 01547 { 01548 #ifdef RIO_DEBUG2 01549 TCPCONNECTIONLOG << "CTcpConnection::Initialize o objeto da classe ja " 01550 << "esta inicializado!" << endl; 01551 #endif 01552 01553 #ifdef RIO_DEBUG1 01554 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish1" << endl; 01555 #endif 01556 01557 return ERROR_TCPCONNECTION + ERROR_INITIALIZED; 01558 } 01559 01560 // Inicializa as variaveis da classe. 01561 m_IP = IP; 01562 m_Port = Port; 01563 m_Socket = Socket; 01564 m_ConnectionTimeOut = ConnectionTimeOut; 01565 m_LogRotation = LogRotation; 01566 m_SentSignal = false; 01567 #ifdef RIO_DEBUG2 01568 m_ReceiveCount = 0; 01569 m_SendCount = 0; 01570 #endif 01571 01572 // Cria o socket usado para desbloquear o poll quando dados precisam ser 01573 // enviados ou quando novas conexoes sao estabelecidas (somente no caso do 01574 // servidor). 01575 m_PollSocket = socket( AF_INET, SOCK_DGRAM, 0 ); 01576 if( m_PollSocket < 0 ) 01577 { 01578 #ifdef RIO_DEBUG2 01579 TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " (" 01580 << strerror( errno ) << ") ao criar o socket usado " 01581 << "para desbloquear o poll quando necessario." 01582 << endl; 01583 #endif 01584 01585 #ifdef RIO_DEBUG1 01586 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish2" << endl; 01587 #endif 01588 01589 return ERROR_NETTCP + ERROR_SOCKET_CREATE; 01590 } 01591 01592 // Faz com que o socket seja exclusivo do processo, e nao seja passado 01593 // para um outro processo criado pelo processo que abriu o socket. 01594 if( fcntl( m_PollSocket, F_SETFD, FD_CLOEXEC ) < 0 ) 01595 { 01596 #ifdef RIO_DEBUG2 01597 TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " (" 01598 << strerror( errno ) << ") ao fazer o socket usado " 01599 << "para desbloquear o poll ser exclusivo ao processo " 01600 << "que criou o objeto da classe CTcpConnection." 01601 << endl; 01602 #endif 01603 01604 #ifdef RIO_DEBUG1 01605 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish3" << endl; 01606 #endif 01607 01608 return ERROR_NETTCP + ERROR_SOCKET_OPTIONS; 01609 } 01610 01611 // Limpa a estrutura TempAddr. 01612 memset( &TempAddr, 0, sizeof( TempAddr ) ); 01613 // associa o socket UDP usado para desbloquear o poll ao IP do servidor e 01614 // a uma porta escolhida aleatoriamente (isso esta bom, ou devemos usar a 01615 // porta do UDP mais 1 - para nao colidir com a porta UDP da RioNeti?). 01616 TempAddr.sin_family = AF_INET; 01617 TempAddr.sin_addr.s_addr = HostIP; 01618 TempAddr.sin_port = 0; // O sistema escolhe a porta. 01619 if( bind( m_PollSocket, ( struct sockaddr * ) &TempAddr, 01620 sizeof( TempAddr ) ) < 0 ) 01621 { 01622 #ifdef RIO_DEBUG2 01623 TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " (" 01624 << strerror( errno ) << ") ao ligar o socket usado " 01625 << "para desbloquear o poll ao IP " 01626 << inet_ntoa( TempAddr.sin_addr ) << "." << endl; 01627 #endif 01628 01629 #ifdef RIO_DEBUG1 01630 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish4" << endl; 01631 #endif 01632 01633 return ERROR_NETTCP + ERROR_SOCKET_BIND; 01634 } 01635 01636 AddrSize = sizeof( m_PollSocketAddr ); 01637 if( getsockname( m_PollSocket, ( struct sockaddr * ) &m_PollSocketAddr, 01638 &AddrSize ) != 0 ) 01639 { 01640 #ifdef RIO_DEBUG2 01641 TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " (" 01642 << strerror( errno ) << ") ao obter as informacoes do " 01643 << "socket usado para desbloquear o poll ao IP " 01644 << inet_ntoa( TempAddr.sin_addr ) << "." << endl; 01645 #endif 01646 01647 #ifdef RIO_DEBUG1 01648 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish5" << endl; 01649 #endif 01650 01651 return ERROR_NETTCP + ERROR_SOCKET_OPTIONS; 01652 } 01653 01654 #ifdef RIO_DEBUG2 01655 TCPCONNECTIONLOG << "CTcpConnection::Initialize socket usado para " 01656 << "desbloquear o poll criado sucesso. O identificador do " 01657 << "socket e " << m_PollSocket << ", e foi associado ao " 01658 << "endereco IP " << inet_ntoa( m_PollSocketAddr.sin_addr ) 01659 << " e a porta " << ntohs( m_PollSocketAddr.sin_port ) 01660 << "." << endl; 01661 #endif 01662 01663 // Inicializa os atributos da thread usada para gerenciar as transferencias 01664 // de dados. 01665 pthread_attr_init( &attribTcpNetMgrThread ); 01666 // Inicializa a pilha da thread usada para gerenciar as transferencias de 01667 // dados. 01668 pthread_attr_setstacksize( &attribTcpNetMgrThread, 2 * PTHREAD_STACK_MIN ); 01669 01670 // Cria a thread usada para gerenciar as transferencias de dados. 01671 if ( pthread_create( &m_TcpNetMgrThreadId, &attribTcpNetMgrThread, 01672 TcpNetMgrThreadEp, ( void * ) this ) != 0 ) 01673 { 01674 #ifdef RIO_DEBUG2 01675 TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno 01676 << " (" << strerror( errno ) << ") ao criar a thread " 01677 << "TcpNetMgrThread." << endl; 01678 #endif 01679 01680 #ifdef RIO_DEBUG1 01681 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish6" << endl; 01682 #endif 01683 01684 return ERROR_TCPCONNECTION + ERROR_CREATE_THREAD; 01685 } 01686 01687 // Desassocia a thread criada par a nova conexao TCP da thread que criou a 01688 // conexao TCP. 01689 pthread_detach( m_TcpNetMgrThreadId ); 01690 01691 // Informa que o objeto foi inicializado com sucesso. 01692 m_Initialized = true; 01693 01694 #ifdef RIO_DEBUG1 01695 TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish7" << endl; 01696 #endif 01697 01698 return S_OK; 01699 }
RioResult CTcpConnection::PutSendData | ( | char * | Data, | |
unsigned int | DataSize, | |||
void * | Param, | |||
unsigned int * | SendDataSize | |||
) |
Funcao para inserir um conjunto de dados a serem enviados posteriormente pelo socket da conexao TCP.
Data | ponteiro para o endereco do inicio dos dados a serem enviados. | |
DataSize | tamanho dos dados a serem enviados (em bytes). | |
Param | parametro a ser passado quando os dados forem enviados (passado ao chamarmos a funcao SendData da classe CNetTCP). | |
SendDataSize | ponteiro para armazenar o tamanho atual da fila. Se o tamanho for 1, precisaremos desbloquear o select. |
Definition at line 1799 of file NetTcp.cpp.
01802 { 01803 // Armazena os dados a serem colocados na fila 01804 SSendData SendData; 01805 01806 #ifdef RIO_DEBUG2 01807 // Armazena o endereco ip para ser usado pela funcao inet_ntoa 01808 in_addr ip; 01809 #endif 01810 01811 #ifdef RIO_DEBUG1 01812 TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Start" << endl; 01813 #endif 01814 01815 #ifdef RIO_DEBUG2 01816 // Inicializa o ip com o IP do objeto. 01817 ip.s_addr = m_IP; 01818 #endif 01819 01820 // Verifica se o objeto da classe ja foi inicializado. 01821 if( !m_Initialized ) 01822 { 01823 #ifdef RIO_DEBUG2 01824 TCPCONNECTIONLOG << "CTcpConnection::PutSendData o objeto da classe " 01825 << "nao esta inicializado!" << endl; 01826 #endif 01827 01828 #ifdef RIO_DEBUG1 01829 TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish1" 01830 << endl; 01831 #endif 01832 01833 return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED; 01834 } 01835 01836 // Obtem o lock para o acesso exclusivo as estruturas do objeto. 01837 pthread_mutex_lock( &m_Mutex ); 01838 01839 // Verificamos se estamos fechando o socket pois, caso o socket esteja sendo 01840 // fechado, nao tem sentido colocar dados na fila. 01841 if( m_isClosingSocket ) 01842 { 01843 // Libera o acesso exlusivo ao lock. 01844 pthread_mutex_unlock( &m_Mutex ); 01845 01846 #ifdef RIO_DEBUG2 01847 TCPCONNECTIONLOG << "CTcpConnection::PutSendData o socket com a ID " 01848 << m_Socket << " esta sendo fechado. Nao e possivel " 01849 << "portanto colocar mais dados na fila de saida." 01850 << endl; 01851 #endif 01852 01853 #ifdef RIO_DEBUG1 01854 TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish2" << endl; 01855 #endif 01856 01857 return ERROR_TCPCONNECTION + ERROR_NOTCONNECTED; 01858 } 01859 01860 // Inicializa os campos dos dados a serem enviados. 01861 SendData.Data = Data; 01862 SendData.DataSize = DataSize; 01863 SendData.Param = Param; 01864 01865 // Tenta colocar os dados na fila. 01866 try 01867 { 01868 #ifdef RIO_DEBUG2 01869 TCPCONNECTIONLOG << "CTcpConnection::PutSendData tentando colocar os " 01870 << "dados a serem enviados pelo socket com a ID " 01871 << m_Socket << ". Tamanho da fila e de " 01872 << m_SendQueue.size() << "." << endl; 01873 #endif 01874 01875 m_SendQueue.push( SendData ); 01876 01877 #ifdef RIO_DEBUG2 01878 TCPCONNECTIONLOG << "CTcpConnection::PutSendData os dados a serem " 01879 << "enviados pelo socket com a ID " << m_Socket 01880 << ", o IP " << inet_ntoa( ip ) << " e a porta " 01881 << ntohs( m_Port ) << " foram colocados na fila com " 01882 << "sucesso. Tamanho da fila agora e de " 01883 << m_SendQueue.size() << "." << endl; 01884 #endif 01885 } 01886 catch( bad_alloc& ba ) 01887 { 01888 // Obtem o tamanho atual da fila. 01889 *SendDataSize = m_SendQueue.size(); 01890 01891 // Libera o acesso exlusivo ao lock. 01892 pthread_mutex_unlock( &m_Mutex ); 01893 01894 #ifdef RIO_DEBUG2 01895 TCPCONNECTIONLOG << "CTcpConnection::PutSendData erro de alocacao de " 01896 << "memoria (bad_alloc, error = " << ba.what() << ") " 01897 << "ao criar uma entrada na fila SendQueue do socket " 01898 << "com a ID " << m_Socket << ", o IP " 01899 << inet_ntoa( ip ) << " e a porta " << ntohs( m_Port ) 01900 << "." << endl; 01901 #endif 01902 01903 #ifdef RIO_DEBUG1 01904 TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish3" << endl; 01905 #endif 01906 01907 return ERROR_TCPCONNECTION + ERROR_MEMORY; 01908 01909 } 01910 01911 // Obtem o tamanho atual da fila. 01912 *SendDataSize = m_SendQueue.size(); 01913 01914 // Tenta desbloquear o poll para que o socket associado ao dado 01915 // enviado possa ser verificado. Como o socket somente nao estara no 01916 // conjunto de saida quando nao existir nenhum dado pendente para ser 01917 // enviado, entao precisamos enviar uma mensagem pelo socket 01918 // m_PollSocket usado para desbloquear o poll somente se SendDataSize for 1. 01919 if( ( *SendDataSize ) == 1 ) 01920 { 01921 #ifdef RIO_DEBUG2 01922 TCPCONNECTIONLOG << "CTcpConnection::PutSendData tentanto desbloquear " 01923 << "o poll, enviando a mensagem \"" << MSG_POLL_NEWDATA 01924 << "\" ao socket com a ID " << m_PollSocket << "." 01925 << endl; 01926 #endif 01927 if( sendto( m_PollSocket, ( void * ) MSG_POLL_NEWDATA, 01928 MSG_POLL_SIZE, UDP_FLAGS_SEND, 01929 ( struct sockaddr * ) &m_PollSocketAddr, 01930 sizeof( m_PollSocketAddr ) ) < 0 ) 01931 { 01932 #ifdef RIO_DEBUG2 01933 TCPCONNECTIONLOG << "CTcpConnection::PutSendData erro " << errno 01934 << " (" << strerror( errno ) << ") ao enviar " 01935 << "dados pelo socket usado para desbloquear o " 01936 << "poll com a ID " << m_PollSocket 01937 << ". Esperando entao pelo proximo dado a ser " 01938 << "enviado!" << endl; 01939 #endif 01940 } 01941 } 01942 01943 // Libera o acesso exlusivo ao lock. 01944 pthread_mutex_unlock( &m_Mutex ); 01945 01946 #ifdef RIO_DEBUG1 01947 TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish4" << endl; 01948 #endif 01949 01950 return S_OK; 01951 }
RioResult CTcpConnection::ReceiveStreamData | ( | char ** | Data, | |
unsigned int * | DataSize | |||
) | [private] |
Funcao para receber dados de uma conexao TCP associada ao stream.
Data | ponteiro que ira armazenar o ponteiro em que os dados foram armazenados | |
DataSize | ponteiro para armazenar o tamanho dos dados lidos. |
Definition at line 200 of file NetTcp.cpp.
00202 { 00203 // Armazena os erros ao chamar as funcoes da biblioteca do C. 00204 ssize_t BytesReceived; 00205 // Variavel usada para armazenar o valor do tamanho convertido para a ordem 00206 // de bytes usada na rede. 00207 unsigned int NetDataSize; 00208 00209 #ifdef RIO_DEBUG1 00210 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Start" << endl; 00211 #endif 00212 00213 // Armazena o endereco IP do stream (para a funcao inet_ntoa). 00214 struct in_addr ip; 00215 00216 #ifdef RIO_DEBUG2 00217 // Estruturas usadas para medir o tempo de execucao de cada funcao da 00218 // thread. 00219 struct timeval Start, End; 00220 unsigned int DiffTime; 00221 #endif 00222 00223 // Copia o endereco associado ao stream. 00224 ip.s_addr = m_IP; 00225 00226 // Atualiza o tempo do timeout. 00227 m_LastUseTime = time( NULL ); 00228 00229 #ifdef RIO_DEBUG2 00230 // Obtem o tempo antes de executar recv (tamanho). 00231 gettimeofday( &Start, NULL ); 00232 #endif 00233 00234 // Tenta receber primeiramente o tamanho dos dados. 00235 BytesReceived = recv( m_Socket, &NetDataSize, sizeof( unsigned int ), 00236 TCP_FLAGS_RECEIVE ); 00237 00238 #ifdef RIO_DEBUG2 00239 // Obtem o tempo depois de executar recv (tamanho). 00240 gettimeofday( &End, NULL ); 00241 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 00242 ( End.tv_usec - Start.tv_usec ) / 1000; 00243 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData tempo para executar " 00244 << "a funcao recv (tamanho) para o socket com a ID " 00245 << m_Socket << ": " << DiffTime << " ms." << endl; 00246 #endif 00247 00248 // Verifica se o tamanho foi recebido corretamente. 00249 if( BytesReceived < 0 ) 00250 { 00251 #ifdef RIO_DEBUG2 00252 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData " << errno 00253 << " (" << strerror( errno ) << ") ao receber o " 00254 << "tamanho do endereco IP " << inet_ntoa( ip ) 00255 << " e a porta " << ntohs( m_Port ) << " a partir " 00256 << "do socket com a ID " << m_Socket << "." << endl; 00257 #endif 00258 00259 *Data = NULL; 00260 *DataSize = 0; 00261 00262 #ifdef RIO_DEBUG1 00263 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish1" 00264 << endl; 00265 #endif 00266 00267 return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE; 00268 } 00269 else if( BytesReceived != sizeof( unsigned int ) ) 00270 { 00271 *Data = NULL; 00272 *DataSize = 0; 00273 00274 if( BytesReceived == 0 ) 00275 { 00276 // Neste caso, possivelmente ocorreu uma queda na conexao que ainda 00277 // nao foi detectada. Por isso, vamos retornar S_OK, pois o efeito 00278 // sera similar ao de receber uma mensagem com tamanho igual a 0. 00279 // Reportamos isso no log para fins de depuracao. 00280 #ifdef RIO_DEBUG2 00281 TCPCONNECTIONLOG << "[CTcpConnection] Tentamos receber dados pela " 00282 << "conexao TCP do IP " << inet_ntoa( ip ) 00283 << " e a porta " << ntohs( m_Port ) << ", mas " 00284 << "nenhum dado chegou pelo socket com a ID " 00285 << m_Socket << ". Logo, esta conexao TCP sera " 00286 << "entao fechada!" << endl; 00287 #endif 00288 00289 #ifdef RIO_DEBUG1 00290 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish2" 00291 << endl; 00292 #endif 00293 00294 // Retorna S_OK para que a acao tomada na thread TcpNetMgrThread 00295 // seja similar a do termino de uma conexao devido a termos recebido 00296 // uma mensasem com tamanho igual a 0. 00297 return S_OK; 00298 } 00299 else 00300 { 00301 // Neste caso realmente ocorreu um erro, pois nao recebemos bytes 00302 // sufucientes para um tamanho de dados. 00303 00304 #ifdef RIO_DEBUG2 00305 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData nao foram " 00306 << "recebidos bytes suficientes ao receber o " 00307 << "tamanho dos dados do endereco IP " 00308 << inet_ntoa( ip ) << " e a porta " 00309 << ntohs( m_Port ) << " pelo socket com a ID " 00310 << m_Socket << ". Foram recebidos " 00311 << BytesReceived << " bytes, mas deveriam ser " 00312 << sizeof( unsigned int ) << " bytes." << endl; 00313 #endif 00314 00315 #ifdef RIO_DEBUG1 00316 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish3" 00317 << endl; 00318 #endif 00319 00320 return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE; 00321 } 00322 } 00323 00324 // Converte o tamanho da ordem da rede para a ordem da maquina. 00325 *DataSize = ntohl( NetDataSize ); 00326 00327 // Recebe os dados se o tamanho for maior do que 0. Se o tamanho for igual a 00328 // 0, isso indicara que a conexao TCP foi fechada pelo outro lado. 00329 if( DataSize > 0 ) 00330 { 00331 // Tenta alocar o buffer para receber os dados. 00332 try 00333 { 00334 #ifdef RIO_DEBUG2 00335 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData tentando " 00336 << "alocar um vetor com " << *DataSize << " bytes " 00337 << "para receber dados do socket com a ID " 00338 << m_Socket << "." << endl; 00339 #endif 00340 00341 *Data = new char[ *DataSize ]; 00342 00343 #ifdef RIO_DEBUG2 00344 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData vetor com " 00345 << *DataSize << " bytes alocado com sucesso para " 00346 << "receber dados do socket com a ID " << m_Socket 00347 << "." << endl; 00348 #endif 00349 } 00350 catch( bad_alloc &ba ) 00351 { 00352 #ifdef RIO_DEBUG2 00353 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData memoria " 00354 << "insuficiente para criar o buffer com " 00355 << *DataSize << " bytes para receber os dados " 00356 << "do endereco IP " << inet_ntoa( ip ) 00357 << " e a porta " << ntohs( m_Port ) 00358 << " pelo socket com a ID " << m_Socket 00359 << " (bad_alloc, error = " << ba.what() << ")." 00360 << endl; 00361 #endif 00362 00363 *DataSize = 0; 00364 *Data = NULL; 00365 00366 #ifdef RIO_DEBUG1 00367 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish4" 00368 << endl; 00369 #endif 00370 00371 return ERROR_TCPCONNECTION + ERROR_MEMORY; 00372 00373 } 00374 00375 #ifdef RIO_DEBUG2 00376 // Obtem o tempo antes de executar recv (dados) 00377 gettimeofday( &Start, NULL ); 00378 #endif 00379 00380 // Agora recebemos os dados pela conexao TCP 00381 BytesReceived = recv( m_Socket, *Data, *DataSize, TCP_FLAGS_RECEIVE ); 00382 00383 #ifdef RIO_DEBUG2 00384 // Obtem o tempo depois de executar recv (dados). 00385 gettimeofday( &End, NULL ); 00386 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 00387 ( End.tv_usec - Start.tv_usec ) / 1000; 00388 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData tempo para " 00389 << "executar a funcao recv (dados) para o socket com " 00390 << "a ID " << m_Socket << ": " << DiffTime << " ms." 00391 << endl; 00392 #endif 00393 00394 // Verifica se os dados foram recebidos corretamente. 00395 if( BytesReceived < 0 ) 00396 { 00397 #ifdef RIO_DEBUG2 00398 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData erro " 00399 << errno << " (" << strerror( errno ) << ") ao " 00400 << "receber os dados do endereco IP " 00401 << inet_ntoa( ip ) << " e a porta " 00402 << ntohs( m_Port ) << "pelo socket com a ID " 00403 << m_Socket << "." << endl; 00404 #endif 00405 00406 // Remove o buffer alocado anteriormente. 00407 delete[] *Data; 00408 00409 *Data = NULL; 00410 *DataSize = 0; 00411 00412 #ifdef RIO_DEBUG1 00413 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish5" 00414 << endl; 00415 #endif 00416 00417 return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE; 00418 } 00419 else if( ( ( unsigned int ) BytesReceived ) != *DataSize ) 00420 { 00421 #ifdef RIO_DEBUG2 00422 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData os dados " 00423 << "do endereco IP " << inet_ntoa( ip ) << " e a " 00424 << "porta " << ntohs( m_Port ) << "pelo " 00425 << "socket com a ID " << m_Socket << " foram " 00426 << "recebidos parcialmente, pois somente chegaram " 00427 << BytesReceived << " bytes do total de " 00428 << DataSize << "bytes." << endl; 00429 #endif 00430 00431 // Remove o buffer alocado anteriormente. 00432 delete[] *Data; 00433 00434 *Data = NULL; 00435 *DataSize = 0; 00436 00437 #ifdef RIO_DEBUG1 00438 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish6" 00439 << endl; 00440 #endif 00441 00442 return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE; 00443 } 00444 } 00445 00446 #ifdef RIO_DEBUG2 00447 // Atualiza o contador de recebimento de dados. 00448 m_ReceiveCount++; 00449 00450 TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData foram recebidos " 00451 << *DataSize << " bytes com sucesso pelo socket com a ID " 00452 << m_Socket << "." << endl; 00453 #endif 00454 00455 #ifdef RIO_DEBUG1 00456 TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish7" 00457 << endl; 00458 #endif 00459 00460 return S_OK; 00461 }
RioResult CTcpConnection::SendStreamData | ( | unsigned int * | DataSize, | |
void ** | Param | |||
) | [private] |
Funcao para enviar o primeiro bloco de dados pendente em um stream TCP.
DataSize | ponteiro para um parametro que armazenara o tamanho dos dados enviados. | |
Param | ponteiro para o parametro passado quando os dados forem enviados pela funcao SendData. |
Definition at line 464 of file NetTcp.cpp.
00465 { 00466 // Armazena o erro retornado pelas chamadas ao sistema. 00467 ssize_t BytesSended; 00468 // Armazenam o erro retornado pelas funcoes do RIO. 00469 RioResult RioStatus; 00470 // Variavel usada para armazenar o valor do tamanho convertido para a ordem 00471 // de bytes usada na rede. 00472 unsigned int NetDataSize; 00473 // Variavel usada para armazenar um ponteiro para os dados. 00474 char *Data; 00475 00476 #ifdef RIO_DEBUG1 00477 TCPCONNECTIONLOG << "[CTcpConnection - SendStreamData] Start" << endl; 00478 #endif 00479 00480 #ifdef RIO_DEBUG2 00481 // Armazena o endereco IP do stream (para a funcao inet_ntoa). 00482 struct in_addr ip; 00483 00484 // Estruturas usadas para medir o tempo de execucao de cada funcao da 00485 // thread. 00486 struct timeval Start, End; 00487 unsigned int DiffTime; 00488 #endif 00489 00490 // Inicializa o erro retornado pela funcao. 00491 RioStatus = S_OK; 00492 00493 // Inicializa o tamanho dos dados enviados e o identificador da 00494 // transferencia 00495 *DataSize = 0; 00496 *Param = NULL; 00497 00498 #ifdef RIO_DEBUG2 00499 // Usado somente quando a depuracao do codigo estiver ativa. 00500 ip.s_addr = m_IP; 00501 #endif 00502 00503 // Atualiza o tempo do timeout. 00504 m_LastUseTime = time( NULL ); 00505 00506 #ifdef RIO_DEBUG2 00507 // Obtem o tempo antes de executar GetSendData. 00508 gettimeofday( &Start, NULL ); 00509 #endif 00510 00511 // Obtem os dados a serem enviados. 00512 RioStatus = GetSendData( &Data, DataSize, Param ); 00513 if( FAILED( RioStatus ) ) 00514 { 00515 #ifdef RIO_DEBUG2 00516 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData erro 0x" << hex 00517 << RioStatus << dec << " (" 00518 << GetErrorDescription( RioStatus ) << ") ao obter os " 00519 << "dados a serem enviados pela conexao TCP com o " 00520 << "socket com a ID " << m_Socket << "." << endl; 00521 #endif 00522 00523 #ifdef RIO_DEBUG1 00524 TCPCONNECTIONLOG << "[CTcpConnection - SendStreamData] Finish1" << endl; 00525 #endif 00526 00527 return RioStatus; 00528 } 00529 00530 #ifdef RIO_DEBUG2 00531 // Obtem o tempo depois de executar GetSendData. 00532 gettimeofday( &End, NULL ); 00533 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 00534 ( End.tv_usec - Start.tv_usec ) / 1000; 00535 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para executar a " 00536 << "funcao GetSendData para o socket com a ID " << m_Socket 00537 << ": " << DiffTime << " ms." << endl; 00538 #endif 00539 00540 // Verifica se temos dados para enviar (se nao temos dados, entao estamos 00541 // enviando uma mensagem para finalizar a conexao. 00542 if( *DataSize != 0 ) 00543 { 00544 // Neste caso estamos enviando dados ao outro lado (e nao terminando a 00545 // conexao). 00546 00547 // Converte o tamanho da ordem de bytes da maquina para a ordem de bytes 00548 // da rede 00549 NetDataSize = htonl( *DataSize ); 00550 00551 // Tenta enviar os dados. Primeiramente enviaremos o tamanho dos dados, 00552 // para depois enviar os dados. 00553 00554 // Primeramente tenta enviar o tamaho dos dados. 00555 #ifdef RIO_DEBUG2 00556 //Obtem o tempo antes de executar send (tamahho). 00557 gettimeofday( &Start, NULL ); 00558 #endif 00559 00560 BytesSended = send( m_Socket, &NetDataSize, sizeof( unsigned int ), 00561 TCP_FLAGS_SENDSIZE ); 00562 00563 #ifdef RIO_DEBUG2 00564 // Obtem o tempo depois de executar send (tamanho). 00565 gettimeofday( &End, NULL ); 00566 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 00567 ( End.tv_usec - Start.tv_usec ) / 1000; 00568 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para " 00569 << "executar a funcao send (tamanho) para o socket " 00570 << "com a ID " << m_Socket << ": " << DiffTime 00571 << " ms." << endl; 00572 #endif 00573 00574 // Verifica se ocorreu um erro ao enviar o tamanho. 00575 if( BytesSended < 0 ) 00576 { 00577 #ifdef RIO_DEBUG2 00578 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData " << errno 00579 << " (" << strerror( errno ) << ") ao enviar " 00580 << "o tamanho " << *DataSize << " ao endereco IP " 00581 << inet_ntoa( ip ) << " e a porta " 00582 << ntohs( m_Port ) << " pelo socket com a ID " 00583 << m_Socket << "." << endl; 00584 #endif 00585 00586 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND; 00587 } 00588 else if( BytesSended != sizeof( unsigned int ) ) 00589 { 00590 #ifdef RIO_DEBUG2 00591 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData nao foram " 00592 << "enviados bytes suficientes ao enviar o " 00593 << "tamanho dos dados para o endereco IP " 00594 << inet_ntoa( ip ) << " e a porta " 00595 << ntohs( m_Port ) << " pelo socket com a ID " 00596 << m_Socket << "." << endl; 00597 #endif 00598 00599 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND; 00600 } 00601 else 00602 { 00603 #ifdef RIO_DEBUG2 00604 // Obtem o tempo antes de executar CreateStreamsSet 00605 gettimeofday( &Start, NULL ); 00606 #endif 00607 00608 // Primeramente tenta enviar o tamaho dos dados. 00609 // Agora que conseguimos enviar o tamanho com sucesso, passamos 00610 // entao ao envio dos dados. 00611 BytesSended = send( m_Socket, Data, *DataSize, TCP_FLAGS_SENDDATA ); 00612 00613 #ifdef RIO_DEBUG2 00614 // Obtem o tempo depois de executar CreateStreamsSet. 00615 gettimeofday( &End, NULL ); 00616 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 00617 ( End.tv_usec - Start.tv_usec ) / 1000; 00618 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para " 00619 << "executar a funcao send (dados) para o socket " 00620 << "com a ID : " << DiffTime << " ms." << endl; 00621 #endif 00622 00623 // Verifica se ocorreu um erro ao enviar os dados. 00624 if( BytesSended < 0 ) 00625 { 00626 #ifdef RIO_DEBUG2 00627 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData " << errno 00628 << " (" << strerror( errno ) << ") ao enviar " 00629 << "os dados ao endereco IP " 00630 << inet_ntoa( ip ) << " e a porta " 00631 << ntohs( m_Port ) << " pelo socket com a ID " 00632 << m_Socket << "." << endl; 00633 #endif 00634 00635 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND; 00636 } 00637 else if( ( ( unsigned int ) BytesSended ) != *DataSize ) 00638 { 00639 #ifdef RIO_DEBUG2 00640 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData os dados " 00641 << "do endereco IP "<< inet_ntoa( ip ) 00642 << " e a porta " << ntohs( m_Port ) << "pelo " 00643 << "socket com a ID " << m_Socket << " foram " 00644 << "enviados parcialmente, pois somente foram " 00645 << BytesSended << " bytes do total de " 00646 << *DataSize << "bytes." << endl; 00647 #endif 00648 00649 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND; 00650 } 00651 #ifdef RIO_DEBUG2 00652 else 00653 { 00654 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData foram " 00655 << "enviados " << *DataSize << " bytes com " 00656 << "sucesso pela conexao TCP com o socket com " 00657 << "a ID " << m_Socket << "." << endl; 00658 00659 // Atualiza o contador de envio de dados. 00660 m_SendCount++; 00661 } 00662 #endif 00663 } 00664 } 00665 else 00666 { 00667 // Neste caso estamos finalizando a conexao. Precisamos enviar uma 00668 // mensagem com tamanho 0 ao outro lado da conexao. 00669 NetDataSize = htonl( 0 ); 00670 00671 #ifdef RIO_DEBUG2 00672 // Obtem o tempo antes de executar send (tamanho 0). 00673 gettimeofday( &Start, NULL ); 00674 #endif 00675 00676 // Tenta enviar o tamamnho 0. 00677 BytesSended = send( m_Socket, &NetDataSize, sizeof( unsigned int ), 00678 TCP_FLAGS_SENDDATA ); 00679 00680 #ifdef RIO_DEBUG2 00681 // Obtem o tempo depois de executar (tamanho 0). 00682 gettimeofday( &End, NULL ); 00683 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 00684 ( End.tv_usec - Start.tv_usec ) / 1000; 00685 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para " 00686 << "executar a funcao send (tamanho 0) para o " 00687 << "socket com a ID " << m_Socket << ": " << DiffTime 00688 << " ms." << endl; 00689 #endif 00690 00691 // Verifica se ocorreu um erro ao enviar o tamanho 0. 00692 if( BytesSended < 0 ) 00693 { 00694 #ifdef RIO_DEBUG2 00695 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData " << errno 00696 << " (" << strerror( errno ) << ") ao enviar o " 00697 << "tamanho "<< *DataSize << " ao endereco IP " 00698 << inet_ntoa( ip ) << " e a porta " 00699 << ntohs( m_Port ) << " para o socket com a ID " 00700 << m_Socket << "." << endl; 00701 #endif 00702 00703 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND; 00704 } 00705 else if( BytesSended != sizeof( unsigned int ) ) 00706 { 00707 #ifdef RIO_DEBUG2 00708 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData nao foram " 00709 << "enviados bytes suficientes ao enviar o " 00710 << "tamanho dos dados para o endereco IP " 00711 << inet_ntoa( ip ) << " e a porta " 00712 << ntohs( m_Port ) << " pelo socket com a ID " 00713 << m_Socket << "." << endl; 00714 #endif 00715 00716 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND; 00717 } 00718 } 00719 00720 #ifdef RIO_DEBUG1 00721 TCPCONNECTIONLOG << "[CTcpConnection - SendStreamData] Finish2" << endl; 00722 #endif 00723 00724 return RioStatus; 00725 }
bool CTcpConnection::TcpNetMgrThread | ( | void | ) | [private] |
Funcao que efetivamente executa o codigo da thread de gerenciamento da reda, chamada pela funcao ReceiveThreadEp (esta funcao e usada para facilitar o acesso aos campos do objeto).
Definition at line 767 of file NetTcp.cpp.
00768 { 00769 // Variavel booleana que diz se ainda devemos receber dados. Esta variavel 00770 // ficara true ate que a conexao seja fechada pelo outro lado (o primeiro 00771 // recv foi finalizado com nenhum byte lido), enviamos uma mensagem, com 00772 // tamanho 0, de termino de conexao, para o outro lado, ou recebemos uma 00773 // mensagem com tamanho 0. 00774 bool isConnectionActive; 00775 // Tempo atual em segundos desde a Epoch (usado para verificar o timeout 00776 // dos streams). 00777 time_t CurrentTime; 00778 // Define o movito para a conexao ter sido fechada quando isConnectionActive 00779 // se tornar false. 00780 EClosedType ClosedType; 00781 // Vetor de sockes usado pelo comando poll 00782 struct pollfd SoketsInfo[ TCPCONNECTIONSOCKETSNUMBER ]; 00783 // Armazena o tempo de timeout do comando poll. Ele sera igual ao tempo de 00784 // timeout do socket TCP associado ao objeto. 00785 int PollTimeOut; 00786 // Armazena o resultado das execucoes das funcoes da classe e do objeto da 00787 // classe CTcpStreams e da classe CNetTcp. 00788 RioResult RioStatus; 00789 // Armazena o resultado da execucao das funcoes da biblioteca do C. 00790 int SystemStatus; 00791 // Usado para impressao do IP. 00792 in_addr ip; 00793 00794 #ifdef RIO_DEBUG2 00795 // Estruturas usadas para medir o tempo de execucao de cada funcao da 00796 // thread. 00797 struct timeval Start, End; 00798 // Estruturas para medir o tempo de execucao da thread, 00799 struct timeval StartThread, EndThread; 00800 00801 unsigned int DiffTime; 00802 #endif 00803 00804 #ifdef RIO_DEBUG1 00805 TCPCONNECTIONLOG << "[CTcpConnection - TcpNetMgrThread] Start" << endl; 00806 #endif 00807 00808 #ifdef RIO_DEBUG2 00809 // Inicializa a contagem de tempo da thread. 00810 if( m_ServerInstance ) 00811 gettimeofday( &StartThread, NULL ); 00812 #endif 00813 00814 // Inicializa a variavel usada pelas impressoes. 00815 ip.s_addr = m_IP; 00816 00817 #ifdef RIO_DEBUG2 00818 // Somente imprime a ID da thread se a thread estiver associada ao servidor 00819 // ou ao storage. 00820 if( m_ServerInstance ) 00821 RioErr << "TCPNETMGRTHREADID START SYSID=" << syscall( SYS_gettid ) 00822 << ", THREADID=" << pthread_self() << ", IP = " 00823 << inet_ntoa( ip ) << ", Port = " << ntohs( m_Port ) 00824 << ", Socket = " << m_Socket << ", SYSTIME = " << time( NULL ) 00825 << endl; 00826 #endif 00827 00828 // Espera ate que a thread seja liberada para inicializar (isso somente 00829 // ocorrera apos a chamada da funcao EnableConnection, e e usado para evitar 00830 // que a threa atrapalhe o processo inicial do estabelecimento da conexao. 00831 // Se o retorno da funcao for true, entao a conexao foi cancelada, e a 00832 // thread foi desbloqueada somente para terminarmos a execucao. 00833 if( WaitEnableConnection() ) 00834 { 00835 #ifdef RIO_DEBUG2 00836 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread a conexao para o " 00837 << "IP " << inet_ntoa( ip ) << ", a porta " 00838 << ntohs( m_Port ) << " e o socket com a ID " 00839 << m_Socket << " foi cancelada. Retornando da thread!" 00840 << endl; 00841 #endif 00842 00843 #ifdef RIO_DEBUG1 00844 TCPCONNECTIONLOG << "[CTcpConnection - TcpNetMgrThread] Finish1" 00845 << endl; 00846 #endif 00847 00848 return false; 00849 } 00850 00851 // Inicializa a estrutura usada pelo poll. A primeira entrada estara 00852 // associada ao socket TCP e a segunda ao socket UDP. 00853 SoketsInfo[ TCPCONNECTIONSOCKETTCP ].fd = m_Socket; 00854 SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events = POLLIN; 00855 SoketsInfo[ TCPCONNECTIONSOCKETUDP ].fd = m_PollSocket; 00856 SoketsInfo[ TCPCONNECTIONSOCKETUDP ].events = POLLIN; 00857 00858 // Inicialmente a conexao esta ativa. 00859 isConnectionActive = true; 00860 00861 // Inicialmente a conexao nao foi fechada, entao o motivo deve estar como 00862 // nao inicializado. 00863 ClosedType = CONNECTIONUNDEFINED; 00864 00865 // Inicializa o tempo de uso do socket. 00866 m_LastUseTime = time( NULL ); 00867 00868 // Fica em um laco ate a conexao deixar de ficar ativa. 00869 while( isConnectionActive ) 00870 { 00871 // Primeiramente iremos verificar se ocorreu um timeout com o socket. 00872 // Caso isso tenha ocorrido, a conexao TCP devera ser fechada, e a 00873 // thread terminada (ou seja, isConnectionActive se tornara false). 00874 // 00875 // Obtem o tempo atual (usado para verificar se algum socket ja teve um 00876 // timeout. O tempo e desde a Epoch). 00877 CurrentTime = time( NULL ); 00878 00879 // Obtem o mutex do objeto da classe. 00880 pthread_mutex_lock( &m_Mutex ); 00881 00882 // Verifica se o socket deu timeout, caso o socket esteja associado a um 00883 // dos servidores (o cliente nao tem timeout). 00884 if( ( m_ServerInstance ) && ( m_ConnectionTimeOut != 0 ) && 00885 ( ( m_LastUseTime + m_ConnectionTimeOut ) < CurrentTime ) && 00886 ( m_SendQueue.empty() ) ) 00887 { 00888 // Neste caso o socket deu timeout. Deveremos entao fechalo, 00889 // remove-lo do stream, e avisar o objeto da classe NetInterface que 00890 // o socket foi fechado. 00891 #ifdef RIO_DEBUG2 00892 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread a conexao " 00893 << "para o IP " << inet_ntoa( ip ) << " e a porta " 00894 << ntohs( m_Port ) << " sera fechada por timeout " 00895 << "porque " << m_LastUseTime + m_ConnectionTimeOut 00896 << " e menor do que " << CurrentTime << " , e nao " 00897 << "existem dados pendentes a serem enviados pelo " 00898 << "socket com a ID " << m_Socket << " porque o " 00899 << "tamanho da fila de envio e de " 00900 << m_SendQueue.size() << "." << endl; 00901 #endif 00902 00903 // Informa que nao vamos mais executar o laco da conexao TCP. 00904 isConnectionActive = false; 00905 00906 // Informa que o motivo da conexao ser fechada foi por timeout. 00907 ClosedType = CONNECTIONTIMEOUT; 00908 } 00909 00910 // Configura o conjunto do poll para o socket TCP para usar ou nao a 00911 // escrita, de acordo com o a fila de saida estar ou nao vazia. 00912 if( m_SendQueue.empty() ) 00913 SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events &= POLLIN; 00914 else 00915 SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events |= POLLOUT; 00916 00917 // Libera o mutex do objeto da classe. 00918 pthread_mutex_unlock( &m_Mutex ); 00919 00920 // Somente executamos o select se a conexao nao foi fechada acima por 00921 // timeout. 00922 if( isConnectionActive ) 00923 { 00924 // Nao ocorreu um timeout do socket. Entao temos que verificar, no 00925 // select, se o socket dever receber ou enviar dados. 00926 00927 // Se e o servidor, calculamos o tempo de timeout. Porem, se e o 00928 // cliente, nao existira um timeout, e setamos 00929 if( m_ServerInstance ) 00930 { 00931 // Calcula o tempo maximo durante o qual o select sera 00932 // bloqueado. 00933 PollTimeOut = m_LastUseTime + m_ConnectionTimeOut - 00934 time( NULL ); 00935 if( PollTimeOut < 0 ) 00936 PollTimeOut = 0; 00937 else // Converte para milisegundos 00938 PollTimeOut = PollTimeOut * 1000; 00939 } 00940 else // No caso de o objeto estar associado a um cliente, 00941 // definiremos o timeout do poll para um valor negativo. Isso 00942 // indicara que o poll deve ficar bloqueado ate receber algo 00943 // de um dos sockets (o cliente nao possui timeout da conexao). 00944 PollTimeOut = -1; 00945 00946 #ifdef RIO_DEBUG2 00947 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread antes de " 00948 << "executar o poll, Flags do socket TCP com a ID " 00949 << m_Socket << ": ["; 00950 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events & POLLIN ) != 0 ) 00951 TCPCONNECTIONLOG << "POLLIN "; 00952 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events & POLLOUT ) != 0 ) 00953 TCPCONNECTIONLOG << "POLLOUT "; 00954 TCPCONNECTIONLOG << "], Flags do socket UDP com a ID " 00955 << m_PollSocket << ": ["; 00956 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].events & POLLIN ) != 0 ) 00957 TCPCONNECTIONLOG << "POLLIN "; 00958 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].events & POLLOUT ) != 0 ) 00959 TCPCONNECTIONLOG << "POLLOUT "; 00960 TCPCONNECTIONLOG << "], Timeout = " << PollTimeOut << "." << endl; 00961 #endif 00962 00963 // Espera pelo socket TCP ou o UDP estar pronto para leitura, ou 00964 // o socket TCP esta pronto para escrita caso existam dados a serem 00965 // enviados. 00966 SystemStatus = poll( SoketsInfo, TCPCONNECTIONSOCKETSNUMBER, 00967 PollTimeOut ); 00968 00969 #ifdef RIO_DEBUG2 00970 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread depois de " 00971 << "executar o poll, erro = " << errno << " (" 00972 << strerror( errno ) << ")." << endl; 00973 #endif 00974 00975 if( SystemStatus < 0 ) 00976 { 00977 if( errno == EINTR ) // Interrupted system call 00978 { 00979 #ifdef RIO_DEBUG2 00980 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread " 00981 << "recebi o erro que a chamada ao " 00982 << "sistema foi interrompida." << endl; 00983 #endif 00984 } 00985 else 00986 { 00987 #ifdef RIO_DEBUG2 00988 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro " 00989 << errno << " (" << strerror( errno ) 00990 << ") ao executar o comando poll para o " 00991 << "socket com a ID " << m_Socket << "." 00992 << endl; 00993 #endif 00994 00995 // Chama a funcao do objeto da classe CNetInterface que 00996 // processa os erros. 00997 m_NetTcp->ProcessError( m_IP, m_Port, ERROR_NETTCP + 00998 ERROR_SOCKETS_SELECT, 00999 "TcpNetMgrThread-poll", 01000 OTHERERROR, 01001 ( void * ) NULLTRANSFERID ); 01002 } 01003 } 01004 else 01005 { 01006 #ifdef RIO_DEBUG2 01007 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread a funcao " 01008 << "poll executada com sucesso!" << endl; 01009 #endif 01010 } 01011 01012 // Verifica se o socket para desbloquear o select foi usado. 01013 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLIN ) != 0 ) 01014 { 01015 01016 // Armazena a mensagem de estado recebida. 01017 char Message[ MSG_POLL_SIZE + 1 ]; 01018 01019 // Inicializa o buffer da mensagem 01020 memset( Message, 0, MSG_POLL_SIZE + 1 ); 01021 01022 // Recebe e imprime uma mensagem informando que o socket UDP foi 01023 // usado para desbloquear o poll. 01024 if( recv( m_PollSocket, Message, MSG_POLL_SIZE, 01025 UDP_FLAGS_RECEIVE ) < 0 ) 01026 { 01027 #ifdef RIO_DEBUG2 01028 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro " 01029 << errno << " (" << strerror( errno ) 01030 << ") ao tentar receber a mensagem usada " 01031 << "para desbloquear o poll." << endl; 01032 #endif 01033 } 01034 #ifdef RIO_DEBUG2 01035 else 01036 { 01037 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread dados " 01038 << "detectados no socket usado para " 01039 << "desbloquear o poll. A mensagem " 01040 << "passada foi \"" << Message << "\"." 01041 << endl; 01042 } 01043 #endif 01044 } 01045 01046 // Verifica se o socket TCP (se o socket ainda estiver em 01047 // TcpReadSocketsSet, isso significara que dados foram recebidos por 01048 // este socket). 01049 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLIN ) != 0 ) 01050 { 01051 // Armazena o ponteiro para o buffer com os dados lidos (alocado 01052 // pela funcao que recebe os dados). 01053 char *ReceivedData; 01054 // Armazena o tamanho dos dados recebidos (definido tambem pela 01055 // funcao que recebe os dados). 01056 unsigned int ReceivedDataSize; 01057 01058 #ifdef RIO_DEBUG2 01059 // Obtem o tempo antes de executar ReceiveStreamData. 01060 gettimeofday( &Start, NULL ); 01061 #endif 01062 01063 // Recebe os dados pelo socket TCP. 01064 RioStatus = ReceiveStreamData( &ReceivedData, 01065 &ReceivedDataSize ); 01066 01067 #ifdef RIO_DEBUG2 01068 // Obtem o tempo depois de executar ReceiveStreamData. 01069 gettimeofday( &End, NULL ); 01070 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 01071 ( End.tv_usec - Start.tv_usec ) / 1000; 01072 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread tempo " 01073 << "para executar a funcao ReceiveStreamData " 01074 << "para o socket com a ID " << m_Socket 01075 << ": " << DiffTime << " ms." << endl; 01076 #endif 01077 01078 // Verifica se ocorreu erro na leitura. 01079 if( FAILED( RioStatus ) ) 01080 { 01081 // Se ocorreu algum erro, devemos avisar para a classe de 01082 // gerenciamento da conexao. 01083 01084 #ifdef RIO_DEBUG2 01085 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro " 01086 << " 0x" << hex << RioStatus << dec << " (" 01087 << GetErrorDescription( RioStatus ) << ") " 01088 << "ao receber dados pela conexao TCP " 01089 << "associada ao IP " << inet_ntoa( ip ) 01090 << ", a porta " << ntohs( m_Port ) 01091 << "pelo socket com o ID " << m_Socket 01092 << endl; 01093 #endif 01094 01095 // Chama a funcao do objeto da classe CNetInterface que 01096 // processa os erros. 01097 m_NetTcp->ProcessError( m_IP, m_Port, RioStatus, 01098 "TcpNetMgrThread-ReceiveStreamData", 01099 RECEIVEERROR, 01100 ( void * ) NULLTRANSFERID ); 01101 } 01102 else 01103 { 01104 // Verifica se o tamanho dos dados e 0. Neste caso, o outro 01105 // lado da conexao fechou a conexao. 01106 if( ReceivedDataSize == 0 ) 01107 { 01108 // Obtem o mutex do objeto da classe. 01109 pthread_mutex_lock( &m_Mutex ); 01110 01111 // Imprime as informacoes de depuracao (se RIO_DEBUG2 01112 // for usado). 01113 #ifdef RIO_DEBUG2 01114 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread " 01115 << "conexao TCP com o IP " 01116 << inet_ntoa( ip ) << ", a porta " 01117 << ntohs( m_Port ) << " e com o " 01118 << "socket com a ID " << m_Socket 01119 << " foi fechada pelo outro lado." 01120 << endl; 01121 #endif 01122 01123 // Remove a flag de escrita pronta do socket. 01124 SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents &= POLLIN; 01125 01126 // Informa que nao vamos mais executar o laco da conexao 01127 // TCP. 01128 isConnectionActive = false; 01129 01130 // Informa que o motivo da conexao ser fechada foi pelo 01131 // outro lado. 01132 ClosedType = CONNECTIONCLOSEDREMOTELLY; 01133 01134 // Libera o mutex do objeto da classe. 01135 pthread_mutex_unlock( &m_Mutex ); 01136 } 01137 else 01138 { 01139 // Neste caso recebemos corretamente um pacote da 01140 // conexao TCP. Entao deveremos chamar a funcao 01141 // responsavel por tratar dos dados recebidos. 01142 #ifdef RIO_DEBUG2 01143 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread " 01144 << "Recebidos " << ReceivedDataSize 01145 << " bytes pelo IP " << inet_ntoa( ip ) 01146 << " e da porta " << ntohs( m_Port ) 01147 << "pelo socket com a ID " 01148 << m_Socket << "." << endl; 01149 #endif 01150 01151 #ifdef RIO_DEBUG2 01152 // Obtem o tempo antes de executar ProcessData. 01153 gettimeofday( &Start, NULL ); 01154 #endif 01155 01156 // Chama a funcao do objeto da classe CNetInterface que 01157 // processa os dados recebidos pela conexao TCP. 01158 m_NetTcp->ProcessData( m_IP, m_Port, ReceivedData, 01159 ReceivedDataSize ); 01160 01161 #ifdef RIO_DEBUG2 01162 // Obtem o tempo depois de executar ProcessData. 01163 gettimeofday( &End, NULL ); 01164 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 01165 ( End.tv_usec - Start.tv_usec ) / 1000; 01166 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread " 01167 << "tempo para executar a funcao " 01168 << "ProcessData para o socket com a " 01169 << "ID " << m_Socket << ": " 01170 << DiffTime << " ms." << endl; 01171 #endif 01172 01173 // Remove o buffer com os dados recebidos (a funcao 01174 // ProcessData deve copiar os dados e nunca usar o 01175 // ponteiro ReceivedData depois de retornar). 01176 delete[] ReceivedData; 01177 } 01178 } 01179 } 01180 01181 // Verifica se o socket TCP pode enviar dados (se ele estiver em 01182 // TcpWriteSocketsSet, isso significara que dados podem ser enviados 01183 // por este socket. 01184 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLOUT ) 01185 != 0 ) 01186 { 01187 // Armazena o tamanho dos dados enviados pelo comando send. 01188 unsigned int DataSize; 01189 void *Param; 01190 01191 #ifdef RIO_DEBUG2 01192 // Obtem o tempo antes de executar SendStreamData. 01193 gettimeofday( &Start, NULL ); 01194 #endif 01195 01196 // Envia o proximo dado pendente pelo socket. 01197 RioStatus = SendStreamData( &DataSize, &Param ); 01198 01199 #ifdef RIO_DEBUG2 01200 // Obtem o tempo depois de executar SendStreamData. 01201 gettimeofday( &End, NULL ); 01202 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 01203 ( End.tv_usec - Start.tv_usec ) / 1000; 01204 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread tempo " 01205 << "para executar a funcao SendStreamData " 01206 << "para o socket com a ID " << m_Socket 01207 << ": " << DiffTime << " ms." << endl; 01208 #endif 01209 01210 // Verifica se ocorreu algum erro ao executar SendStreamData. 01211 if( FAILED( RioStatus ) ) 01212 { 01213 // Se ocorreu algum erro, devemos avisar para a classe de 01214 // gerenciamento da conexao. 01215 #ifdef RIO_DEBUG2 01216 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro " 01217 << "0x" << hex << RioStatus << dec << " (" 01218 << GetErrorDescription( RioStatus ) 01219 << ") ao enviar dados pela conexao TCP " 01220 << "associada ao IP " << inet_ntoa( ip ) 01221 << ", a porta " << ntohs( m_Port ) << " e " 01222 << "o socket com a ID " << m_Socket << "." 01223 << endl; 01224 #endif 01225 01226 // Chama a funcao do objeto da classe CNetInterface que 01227 // processa os erros. 01228 m_NetTcp->ProcessError( m_IP, m_Port, RioStatus, 01229 "TcpNetMgrThread-SendStreamData", 01230 SENDERROR, Param ); 01231 } 01232 else 01233 { 01234 // Verifica se devemos chamar a callback (isso nao ocorrera 01235 // se o tamanho dos dados for 0, pois o tamanho 0 e usado 01236 // para finalizar as conexoes TCP. 01237 if( DataSize == 0 ) 01238 { 01239 // Obtem o mutex do objeto da classe. 01240 pthread_mutex_lock( &m_Mutex ); 01241 01242 #ifdef RIO_DEBUG2 01243 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread " 01244 << "conexao TCP com o IP " 01245 << inet_ntoa( ip ) << ", a porta " 01246 << ntohs( m_Port ) << " e com o " 01247 << "socket com a ID " << m_Socket 01248 << " foi fechada pelo por este lado. " 01249 << endl; 01250 #endif 01251 01252 // Informa que nao vamos mais executar o laco da conexao 01253 // TCP. 01254 isConnectionActive = false; 01255 01256 // Informa que o motivo da conexao ser fechada foi 01257 // porque locamente a conexao foi finalizada. 01258 ClosedType = CONNECTIONCLOSEDLOCALLY; 01259 01260 // Libera o mutex do objeto da classe. 01261 pthread_mutex_unlock( &m_Mutex ); 01262 } 01263 else 01264 { 01265 #ifdef RIO_DEBUG2 01266 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread os " 01267 << DataSize << " bytes dos dados " 01268 << "foram enviados com sucesso pela " 01269 << "conexao TCP com o IP " 01270 << inet_ntoa( ip ) << ", a porta " 01271 << ntohs( m_Port ) 01272 << " e com socket a ID " << m_Socket 01273 << "." << endl; 01274 #endif 01275 01276 // Adiciona os dados que foram enviados no log de envio 01277 // de dados. Porem, antes precisamos verificar se 01278 // deveremos gerar uma linha com os logs 01279 if( ( m_ServerInstance ) && ( m_LogRotation != NULL ) ) 01280 { 01281 // Tamanho suficiente para um numero de ate 4GB 01282 // mais o '\0'. Devemos mudar isso depois? Era assim 01283 // que estava na RioNeti. 01284 char StrPacketSize[ 11 ]; 01285 sprintf( StrPacketSize, "%d", DataSize ); 01286 RioStatus = m_LogRotation->NewLogLine( time( NULL ), 01287 StrPacketSize 01288 ); 01289 #ifdef RIO_DEBUG2 01290 if( FAILED( RioStatus ) ) 01291 TCPCONNECTIONLOG << "CTcpConnection::" 01292 << "TcpNetMgrThread erro 0x" 01293 << hex << RioStatus << dec 01294 << " (" 01295 << GetErrorDescription( 01296 RioStatus ) 01297 << ") ao escrever no log." 01298 << endl; 01299 #endif 01300 } 01301 01302 #ifdef RIO_DEBUG2 01303 // Obtem o tempo antes de executar SendDataCompleted. 01304 gettimeofday( &Start, NULL ); 01305 #endif 01306 01307 // Chama a funcao do objeto da classe CNetInterface, 01308 // para informar que os dados foram enviados. 01309 m_NetTcp->SendDataCompleted( m_IP, m_Port, Param ); 01310 01311 #ifdef RIO_DEBUG2 01312 // Obtem o tempo depois de executar SendDataCompleted. 01313 gettimeofday( &End, NULL ); 01314 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 01315 ( End.tv_usec - Start.tv_usec ) / 1000; 01316 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread " 01317 << "tempo para executar a funcao " 01318 << "SendDataCompleted para o socket " 01319 << "com a ID " << m_Socket << ": " 01320 << DiffTime << " ms." << endl; 01321 #endif 01322 } 01323 } 01324 } 01325 01326 #ifdef RIO_DEBUG2 01327 // Verifica os outros erros que podem ter ocorrido com os sockets 01328 // TCP e UDP. 01329 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLPRI ) 01330 != 0 ) 01331 { 01332 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01333 << "POLLPRI detectado no socket TCP com a " 01334 << "ID " << m_Socket << "." << endl; 01335 } 01336 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLPRI ) 01337 != 0 ) 01338 { 01339 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01340 << "POLLPRI detectado no socket UDP com a " 01341 << "ID " << m_PollSocket << "." << endl; 01342 } 01343 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLERR ) 01344 != 0 ) 01345 { 01346 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01347 << "POLLERR detectado no socket TCP com a " 01348 << "ID " << m_Socket << "." << endl; 01349 } 01350 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLERR ) 01351 != 0 ) 01352 { 01353 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01354 << "POLLERR detectado no socket UDP com a " 01355 << "ID " << m_PollSocket << "." << endl; 01356 } 01357 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLHUP ) 01358 != 0 ) 01359 { 01360 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01361 << "POLLHUP detectado no socket TCP com a " 01362 << "ID " << m_Socket << "." << endl; 01363 } 01364 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLHUP ) 01365 != 0 ) 01366 { 01367 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01368 << "POLLHUP detectado no socket UDP com a " 01369 << "ID " << m_PollSocket << "." << endl; 01370 } 01371 if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLNVAL ) 01372 != 0 ) 01373 { 01374 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01375 << "POLLNVAL detectado no socket TCP com a " 01376 << "ID " << m_Socket << "." << endl; 01377 } 01378 if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLNVAL ) 01379 != 0 ) 01380 { 01381 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento " 01382 << "POLLNVAL detectado no socket UDP com a " 01383 << "ID " << m_PollSocket << "." << endl; 01384 } 01385 #endif 01386 01387 } 01388 } 01389 01390 // Como saimos do laco, isso significa que a conexao TCP foi fechada. 01391 01392 #ifdef RIO_DEBUG2 01393 // Obtem o tempo antes de executar ConnectionClosed. 01394 gettimeofday( &Start, NULL ); 01395 #endif 01396 01397 // Informa ao objeto da classe CNetInterface que a conexao associada a 01398 // conexao TCP foi fechada. 01399 m_NetTcp->ConnectionClosed( m_IP, m_Port, ClosedType ); 01400 01401 #ifdef RIO_DEBUG2 01402 // Obtem o tempo depois de executar ConnectionClosed. 01403 gettimeofday( &End, NULL ); 01404 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 + 01405 ( End.tv_usec - Start.tv_usec ) / 1000; 01406 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread tempo para executar a " 01407 << "funcao ConnectionClosed para o socket com a ID " 01408 << m_Socket << ": " << DiffTime << " ms." << endl; 01409 #endif 01410 01411 // Obtem o mutex do objeto da classe. 01412 pthread_mutex_lock( &m_Mutex ); 01413 01414 // Verifica se o socket a ser fechado tem dados 01415 // pendentes pois, neste caso, nao iremos mais enviar 01416 // dados por ele. 01417 if( m_SendQueue.size() > 0 ) 01418 { 01419 #ifdef RIO_DEBUG2 01420 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread Existia(m) um " 01421 << "conjunto(s) de " << m_SendQueue.size() << " dados " 01422 << "pendentes para serem enviados! Os dados serao ignorados!" 01423 << endl; 01424 #endif 01425 } 01426 01427 // Libera o mutex do objeto da classe. 01428 pthread_mutex_unlock( &m_Mutex ); 01429 01430 // Faz o shutdown no socket. 01431 shutdown( m_Socket, SHUT_RDWR ); 01432 01433 // Fecha o socket associado ao stream TCP. 01434 close( m_Socket ); 01435 01436 // Faz o shudown do socket usado para desbloquear o poll. 01437 shutdown( m_PollSocket, SHUT_RDWR ); 01438 01439 // Fecha o socket usado para desbloquear o poll. 01440 close( m_PollSocket ); 01441 01442 // Imprime as informacoes de depuracao (se RIO_DEBUG2 for 01443 // usado). 01444 #ifdef RIO_DEBUG2 01445 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread conexao TCP com o IP " 01446 << inet_ntoa( ip ) << ", a porta " << ntohs( m_Port ) 01447 << " e com o socket com a ID " << m_Socket << " foi " 01448 << "fechada "; 01449 switch( ClosedType ) 01450 { 01451 case CONNECTIONCLOSEDLOCALLY: 01452 TCPCONNECTIONLOG << "localmente."; 01453 break; 01454 case CONNECTIONCLOSEDREMOTELLY: 01455 TCPCONNECTIONLOG << "remotamente."; 01456 break; 01457 case CONNECTIONTIMEOUT: 01458 TCPCONNECTIONLOG << "devido a um timeout (depois de " 01459 << m_ConnectionTimeOut << " segundos)."; 01460 break; 01461 default: 01462 TCPCONNECTIONLOG << "(valor " << ClosedType << "e o " 01463 << "CONNECTIONUNDEFINED ou invalido, e nao " 01464 << "deveria ter sido usado!)."; 01465 break; 01466 } 01467 TCPCONNECTIONLOG << "Dados enviados = " << m_SendCount << " e dados " 01468 << "recebidos = " << m_ReceiveCount << "." << endl; 01469 #endif 01470 01471 #ifdef RIO_DEBUG2 01472 if( m_ServerInstance ) 01473 { 01474 // Final da a contagem de tempo da thread. 01475 gettimeofday( &EndThread, NULL ); 01476 01477 // Calcula o tempo de execucao em ms. 01478 DiffTime = ( EndThread.tv_sec - StartThread.tv_sec ) * 1000 + 01479 ( EndThread.tv_usec - StartThread.tv_usec ) / 1000; 01480 01481 RioErr << "TCPNETMGRTHREADID END, SYSID=" << syscall( SYS_gettid ) 01482 << ", THREADID=" << pthread_self() << ", IP = " 01483 << inet_ntoa( ip ) << ", Port = " << ntohs( m_Port ) 01484 << ", Socket = " << m_Socket << ", Time = " << DiffTime << "ms." 01485 << endl; 01486 } 01487 #endif 01488 01489 #ifdef RIO_DEBUG1 01490 TCPCONNECTIONLOG << "[CTcpConnection - TcpNetMgrThread] Finish2" << endl; 01491 #endif 01492 01493 return true; 01494 }
void * CTcpConnection::TcpNetMgrThreadEp | ( | void * | ThreadParam | ) | [static, private] |
Funcao que trata da execucao do codigo da thread de gerenciamento das conexoes TCP ativas.
ThreadParam | ponteiro com o parametro da thread. Para esta thread, e um ponteiro para um objeto da classe CNetTcp. |
Definition at line 1499 of file NetTcp.cpp.
01500 { 01501 // Armazena o ponteiro do objeto passado como parametro a thread. 01502 CTcpConnection *TcpConnection = ( CTcpConnection * ) ThreadParam; 01503 // Armazena o retorno da execucao da thread. 01504 bool ThreadResult; 01505 01506 #ifdef RIO_DEBUG1 01507 TCPCONNECTIONLOGEST << "[CTcpConnection - TcpNetMgrThreadEp] Start" << endl; 01508 #endif 01509 01510 // Executa o codigo da thread associada ao objeto TcpConnection. 01511 ThreadResult = TcpConnection->TcpNetMgrThread(); 01512 01513 // Remove o objeto TcpConnection, se ThreadResult for true (Se for false, 01514 // entao a execucao da thread foi abortada, o que significa que o objeto 01515 // sera deletado em outro lugar (isso ocorrera ou na funcao TcpAccept ou 01516 // na funcao TcpConnect da classe CNetTcp. 01517 if( ThreadResult ) 01518 delete TcpConnection; 01519 01520 #ifdef RIO_DEBUG1 01521 TCPCONNECTIONLOGEST << "[CTcpConnection - TcpNetMgrThreadEp] Finish" 01522 << endl; 01523 #endif 01524 01525 return NULL; 01526 }
bool CTcpConnection::WaitEnableConnection | ( | void | ) | [private] |
Funcao para esperar ate que a funcao EnableConnection.
Definition at line 728 of file NetTcp.cpp.
00729 { 00730 // Armazena uma copia de m_isAborted; 00731 bool isAborted; 00732 00733 #ifdef RIO_DEBUG1 00734 TCPCONNECTIONLOG << "[CTcpConnection - WaitEnableConnection] Start" << endl; 00735 #endif 00736 00737 // Obtem o lock do objeto. 00738 pthread_mutex_lock( &m_Mutex ); 00739 00740 // Espera, na variavel de condicao m_Cond, a conexao ser habilitada, somente 00741 // se m_SentSignal for false. 00742 if( !m_SentSignal ) 00743 pthread_cond_wait( &m_Cond, &m_Mutex ); 00744 00745 // Como recebemos o sinal, fazemos m_SentSignal ser false. 00746 m_SentSignal = false; 00747 00748 // Copia o valor de m_isAborted, que informa se devemos continuar a execucao 00749 // da thread (false) ou se a conexao foi abortada e a thread deve ser 00750 // finalizada (true). 00751 00752 isAborted = m_isAborted; 00753 00754 // Libera o acesso exlusivo ao lock. 00755 pthread_mutex_unlock( &m_Mutex ); 00756 00757 #ifdef RIO_DEBUG1 00758 TCPCONNECTIONLOG << "[CTcpConnection - WaitEnableConnection] Finish" 00759 << endl; 00760 #endif 00761 00762 return isAborted; 00763 }
pthread_cond_t CTcpConnection::m_Cond [private] |
time_t CTcpConnection::m_ConnectionTimeOut [private] |
bool CTcpConnection::m_Initialized [private] |
int CTcpConnection::m_IP [private] |
bool CTcpConnection::m_isAborted [private] |
bool CTcpConnection::m_isClosingSocket [private] |
time_t CTcpConnection::m_LastUseTime [private] |
CLogRotation* CTcpConnection::m_LogRotation [private] |
pthread_mutex_t CTcpConnection::m_Mutex [private] |
CNetTcp* CTcpConnection::m_NetTcp [private] |
int CTcpConnection::m_PollSocket [private] |
struct sockaddr_in CTcpConnection::m_PollSocketAddr [private] |
int CTcpConnection::m_Port [private] |
TSendQueue CTcpConnection::m_SendQueue [private] |
bool CTcpConnection::m_SentSignal [private] |
bool CTcpConnection::m_ServerInstance [private] |
int CTcpConnection::m_Socket [private] |
pthread_t CTcpConnection::m_TcpNetMgrThreadId [private] |