Página principal   Lista de namespaces   Hierarquia de classes   Lista de componentes   Lista de ficheiros   Membros do namespace   Componentes   Declarações  

mensageiro.C

Ir para a documentação deste ficheiro.
00001 #include <IPC/mensageiro.H>
00002 
00003 bool IPC::Mensageiro::existe_instancia = false;
00004 
00005 IPC::Mensageiro::Mensageiro(key_t const chave)
00006 {
00007     assert(!existe_instancia);
00008 
00009     existe_instancia = true;
00010 
00011     /* Usa-se por omissão o getuid() para que a comunicação entre
00012        utilizadores não seja possível, eliminando-se assim muitos
00013        problemas. */
00014     int permissoes = (chave == key_t(getuid()))? 0660 : 0666;
00015     
00016     // Obtenção de PID do processo corrente e do UID do utilizador.
00017     eu = int(getpid());
00018     meuUID = int(getuid());
00019     
00020     // Criação de caixa do correio/obtenção de identificador de caixa
00021     // do correio existente:
00022     if((id = msgget(chave, IPC_CREAT | permissoes)) == -1)
00023         throw Erro();
00024 
00025     try {
00026         
00027         /* Tenta ler PID de um servidor do canal 1, que é o canal onde
00028            os servidores se registam.  Se a leitura falhar, não existe
00029            servidor registado, pelo que o corrente processo se
00030            assumirá como servidor. Note-se que esta utilização de
00031            excepções como substitutos de instruções de selecção não é
00032            boa ideia em geral. */
00033         outro = leBasicoInt(1, false);
00034         
00035         /* Encontrou registo de vervidor.  Nesse caso é
00036            cliente. */
00037         servidor = false;
00038         
00039         // Depois escreve o seu PID no canal do servidor */
00040         envia(eu);
00041         
00042     } catch(Erro) {
00043         
00044         /* Não encontrou registo de servidor.  Nesse caso é
00045            servidor e espera por um cliente. */
00046         servidor = true;
00047         
00048         /* O servidor regista a existência de actividade
00049            escrevendo uma mensagem irrelevante no canal 2, que
00050            é usado pelos serviddres para saberem se a caixa do
00051            correio deve ser eliminada quando eles terminam a
00052            execução. */
00053         escreveBasicoInt(2, 0);
00054         
00055         /* O servidor escreve o seu PID no canal 1. */
00056         escreveBasicoInt(1, eu);
00057         
00058         /* Depois fica à espera do PID do cliente mas já no
00059            seu próprio canal. */
00060         outro = intRecebido();
00061     }
00062 
00063     // Envia o UID ao "outro".
00064     envia(meuUID);
00065 
00066     // Recebe o UID do "outro".
00067     outroUID = intRecebido();
00068 }
00069 
00070 IPC::Mensageiro::~Mensageiro() 
00071 {
00072     try {
00073         if(servidor) {
00074 
00075             /* Se é servidor espera por fim do cliente antes de
00076                terminar em paz. */
00077             string mensagem;
00078             while((mensagem = stringRecebida()) != "TeRmInEi")
00079                 ;
00080                 
00081             /* Servidor elimina um marcador de existência de
00082                actividade. */
00083             leBasicoInt(2);
00084 
00085             /* Se não há nenhum marcador de existência de actividade,
00086                remove a caixa do correio. Ver mais acima nota acerca
00087                de blocos de tentativa para substituir instruções de
00088                selecção. */
00089             try {
00090                 leBasicoInt(2, false);
00091                 escreveBasicoInt(2, 0);
00092             } catch(Erro) {
00093                 msgctl(id, IPC_RMID, 0);
00094             }
00095 
00096         } else {
00097             // Clientes avisam servidores que vão terminar.
00098             envia("TeRmInEi");
00099         }
00100     } catch(Erro) {
00101         /* Se houve erro, ignorar...  Excepções em destrutores são
00102            má ideia.  Deixar uma caixa do correio criada não
00103            incomoda muito... */
00104     }
00105 }
00106 
00107 string IPC::Mensageiro::leBasico(int const tipo, bool const espera) 
00108 {
00109     typedef string::size_type Tamanho;
00110     int flag = espera? 0 : IPC_NOWAIT;
00111 
00112     // Receber tamanho da mensagem:
00113     msgbuf *mensagem_ipc = 
00114         static_cast<msgbuf*>(malloc(sizeof(long) + sizeof(Tamanho)));
00115     if(msgrcv(id, mensagem_ipc, sizeof(Tamanho), tipo, flag) == -1)
00116         throw Erro();
00117     Tamanho tamanho;
00118     memcpy(static_cast<void*>(&tamanho), 
00119            static_cast<void*>(mensagem_ipc->mtext),
00120            sizeof(Tamanho));
00121     free(mensagem_ipc);
00122 
00123     // Enviar memsagem:
00124     mensagem_ipc = 
00125         static_cast<msgbuf*>(malloc(sizeof(long) + tamanho + 1));
00126     if(msgrcv(id, mensagem_ipc, tamanho + 1, tipo, flag) == -1)
00127         throw Erro();
00128     string mensagem = mensagem_ipc->mtext;
00129     free(mensagem_ipc);
00130 
00131     return mensagem;
00132 }
00133 
00134 void IPC::Mensageiro::escreveBasico(int const tipo, string const& mensagem) 
00135 {
00136     typedef string::size_type Tamanho;
00137 
00138     // Enviar tamanho da mensagem:
00139     msgbuf *mensagem_ipc = 
00140         static_cast<msgbuf*>(malloc(sizeof(long) + sizeof(Tamanho)));
00141     mensagem_ipc->mtype = tipo;
00142     Tamanho tamanho = mensagem.size();
00143     memcpy(static_cast<void*>(mensagem_ipc->mtext),
00144            static_cast<void*>(&tamanho), sizeof(Tamanho));
00145     if(msgsnd(id, mensagem_ipc, sizeof(Tamanho), IPC_NOWAIT) == -1)
00146         throw Erro();
00147     free(mensagem_ipc);
00148 
00149     // Enviar memsagem:
00150     mensagem_ipc = 
00151         static_cast<msgbuf*>(malloc(sizeof(long) + tamanho + 1));
00152     mensagem_ipc->mtype = tipo;
00153     strcpy(mensagem_ipc->mtext, mensagem.c_str());
00154     if(msgsnd(id, mensagem_ipc, tamanho + 1, IPC_NOWAIT) == -1)
00155         throw Erro();
00156     free(mensagem_ipc);
00157 }

Gerado em Tue Apr 10 15:38:16 2001 para Pacotes por doxygen1.2.6 escrito por Dimitri van Heesch, © 1997-2001