00001
00007 #include <cassert>
00008
00009 #include <IPC++/mensageiro.H>
00010
00011 IPC::Mensageiro::Mensageiro(key_t const chave)
00012 {
00013 assert(not existe_instancia);
00014
00015 existe_instancia = true;
00016
00017
00018 meu_PID = int(getpid());
00019 meu_UID = int(getuid());
00020
00021 estabeleceSemaforoDeAcesso(chave);
00022
00023 entraEmAcessoExclusivo();
00024
00025 estabeleceCaixaDoCorreio(chave);
00026
00027 try {
00028
00029
00030
00031
00032
00033
00034
00035 PID_do_outro = leBasicoInt(1, false);
00036
00037 saiDeAcessoExclusivo();
00038
00039
00040
00041 sou_um_servidor = false;
00042
00043
00044 escreveBasicoInt(PID_do_outro, meu_PID);
00045
00046 } catch(Erro) {
00047
00048
00049
00050 sou_um_servidor = true;
00051
00052
00053
00054
00055
00056
00057 escreveBasicoInt(2, 0);
00058
00059
00060 escreveBasicoInt(1, meu_PID);
00061
00062 saiDeAcessoExclusivo();
00063
00064
00065
00066 PID_do_outro = leBasicoInt(meu_PID);
00067 }
00068
00069
00070 escreveBasicoInt(PID_do_outro, meu_UID);
00071
00072
00073 UID_do_outro = leBasicoInt(meu_PID);
00074 }
00075
00076 IPC::Mensageiro::~Mensageiro()
00077 {
00078 try {
00079 if(sou_um_servidor) {
00080
00081
00082
00083 std::string mensagem;
00084 while((mensagem = leBasico(meu_PID)) != "TeRmInEi")
00085 ;
00086
00087 entraEmAcessoExclusivo();
00088
00089
00090
00091 leBasicoInt(2);
00092
00093
00094
00095
00096
00097 try {
00098 leBasicoInt(2, false);
00099 escreveBasicoInt(2, 0);
00100 } catch(Erro) {
00101 removeCaixaDoCorreio();
00102 }
00103
00104 saiDeAcessoExclusivo();
00105 } else {
00106
00107 escreveBasico(PID_do_outro, "TeRmInEi");
00108 }
00109 } catch(Erro) {
00110
00111
00112
00113 }
00114 }
00115
00116 std::string IPC::Mensageiro::leBasico(int const tipo,
00117 bool const deve_esperar) const
00118 {
00119 typedef std::string::size_type Tamanho;
00120
00121 int tipo_de_leitura = deve_esperar ? 0 : IPC_NOWAIT;
00122
00123
00124 msgbuf *mensagem_ipc =
00125 static_cast<msgbuf*>(malloc(sizeof(long) + sizeof(Tamanho)));
00126
00127 if(msgrcv(identificador_da_caixa_do_correio,
00128 mensagem_ipc, sizeof(Tamanho), tipo, tipo_de_leitura) == -1)
00129 throw Erro();
00130
00131 Tamanho tamanho;
00132 memcpy(static_cast<void*>(&tamanho),
00133 static_cast<void*>(mensagem_ipc->mtext),
00134 sizeof(Tamanho));
00135
00136 free(mensagem_ipc);
00137
00138
00139 mensagem_ipc =
00140 static_cast<msgbuf*>(malloc(sizeof(long) + tamanho + 1));
00141
00142 if(msgrcv(identificador_da_caixa_do_correio,
00143 mensagem_ipc, tamanho + 1, tipo, tipo_de_leitura) == -1)
00144 throw Erro();
00145
00146 std::string mensagem = mensagem_ipc->mtext;
00147
00148 free(mensagem_ipc);
00149
00150 return mensagem;
00151 }
00152
00153 void IPC::Mensageiro::escreveBasico(int const tipo,
00154 std::string const& mensagem) const
00155 {
00156 typedef std::string::size_type Tamanho;
00157
00158
00159 msgbuf *mensagem_ipc =
00160 static_cast<msgbuf*>(malloc(sizeof(long) + sizeof(Tamanho)));
00161
00162 mensagem_ipc->mtype = tipo;
00163 Tamanho tamanho = mensagem.size();
00164 memcpy(static_cast<void*>(mensagem_ipc->mtext),
00165 static_cast<void*>(&tamanho), sizeof(Tamanho));
00166
00167 if(msgsnd(identificador_da_caixa_do_correio,
00168 mensagem_ipc, sizeof(Tamanho), IPC_NOWAIT) == -1)
00169 throw Erro();
00170
00171 free(mensagem_ipc);
00172
00173
00174 mensagem_ipc =
00175 static_cast<msgbuf*>(malloc(sizeof(long) + tamanho + 1));
00176
00177 mensagem_ipc->mtype = tipo;
00178 strcpy(mensagem_ipc->mtext, mensagem.c_str());
00179
00180 if(msgsnd(identificador_da_caixa_do_correio,
00181 mensagem_ipc, tamanho + 1, IPC_NOWAIT) == -1)
00182 throw Erro();
00183
00184 free(mensagem_ipc);
00185 }
00186
00187 void IPC::Mensageiro::estabeleceSemaforoDeAcesso(key_t const chave)
00188 {
00189 #if defined(__GNU_LIBRARY__) and not defined(_SEM_SEMUN_UNDEFINED)
00190
00191 #else
00192
00193 union semun {
00194 int val;
00195 struct semid_ds *buf;
00196 unsigned short int *array;
00197 struct seminfo *__buf;
00198 };
00199 #endif
00200
00201 int permissoes = (chave == key_t(getuid()))? 0660 : 0666;
00202
00203
00204
00205 identificador_do_semaforo =
00206 semget(chave, 1, IPC_CREAT | IPC_EXCL | permissoes);
00207 if(identificador_do_semaforo == -1)
00208 if(errno == EEXIST) {
00209 identificador_do_semaforo = semget(chave, 1, 0);
00210 if(identificador_do_semaforo == -1)
00211 throw Erro();
00212 } else
00213 throw Erro();
00214 else {
00215 semun ctl_arg;
00216 ctl_arg.val = 1;
00217
00218 if(semctl(identificador_do_semaforo, 0, SETVAL, ctl_arg) == -1)
00219 throw Erro();
00220 }
00221 }
00222
00223 bool IPC::Mensageiro::existe_instancia = false;
00224
00225
00226 #ifdef TESTE
00227
00228 #include <iostream>
00229
00230 extern "C" {
00231 #include <unistd.h>
00232 }
00233
00234 using namespace std;
00235 using namespace IPC;
00236
00237 int main()
00238 {
00239 fork();
00240
00241 try {
00242 Mensageiro mensageiro;
00243
00244 mensageiro.envia("olá");
00245
00246 mensageiro.envia(string("olát"));
00247
00248 string s1 = "olé";
00249 mensageiro.envia(s1);
00250
00251 string const s2 = "olí";
00252 mensageiro.envia(s2);
00253
00254 char* s3 = "oló";
00255 mensageiro.envia(s3);
00256
00257 char const* s4 = "oló1";
00258 mensageiro.envia(s4);
00259
00260 char* const s5 = "oló2";
00261 mensageiro.envia(s5);
00262
00263 char const* const s6 = "oló3";
00264 mensageiro.envia(s6);
00265
00266 mensageiro.envia(1.0);
00267
00268 double x1 = 2.0;
00269 mensageiro.envia(x1);
00270
00271 double const x2 = 3.0;
00272 mensageiro.envia(x2);
00273
00274 mensageiro.envia(1);
00275
00276 int i1 = 2;
00277 mensageiro.envia(i1);
00278
00279 int const i2 = 3;
00280 mensageiro.envia(i2);
00281
00282 mensageiro.envia('a');
00283
00284 char c1 = 'b';
00285 mensageiro.envia(c1);
00286
00287 char const c2 = 'c';
00288 mensageiro.envia(c2);
00289
00290 mensageiro.leMensagem();
00291 assert(mensageiro.mensagemLida<string>() == "olá");
00292
00293 mensageiro.leMensagem();
00294 assert(mensageiro.mensagemLida<string>() == "olát");
00295
00296 mensageiro.leMensagem();
00297 assert(mensageiro.mensagemLida<string>() == "olé");
00298
00299 mensageiro.leMensagem();
00300 assert(mensageiro.mensagemLida<string>() == "olí");
00301
00302 mensageiro.leMensagem();
00303 assert(mensageiro.mensagemLida<string>() == "oló");
00304
00305 mensageiro.leMensagem();
00306 assert(mensageiro.mensagemLida<string>() == "oló1");
00307
00308 mensageiro.leMensagem();
00309 assert(mensageiro.mensagemLida<string>() == "oló2");
00310
00311 mensageiro.leMensagem();
00312 assert(mensageiro.mensagemLida<string>() == "oló3");
00313
00314 mensageiro.leMensagem();
00315 assert(mensageiro.mensagemLida<double>() == 1.0);
00316
00317 mensageiro.leMensagem();
00318 assert(mensageiro.mensagemLida<double>() == 2.0);
00319
00320 mensageiro.leMensagem();
00321 assert(mensageiro.mensagemLida<double>() == 3.0);
00322
00323 mensageiro.leMensagem();
00324 assert(mensageiro.mensagemLida<int>() == 1);
00325
00326 mensageiro.leMensagem();
00327 assert(mensageiro.mensagemLida<int>() == 2);
00328
00329 mensageiro.leMensagem();
00330 assert(mensageiro.mensagemLida<int>() == 3);
00331
00332 mensageiro.leMensagem();
00333 assert(mensageiro.mensagemLida<char>() == 'a');
00334
00335 mensageiro.leMensagem();
00336 assert(mensageiro.mensagemLida<char>() == 'b');
00337
00338 mensageiro.leMensagem();
00339 assert(mensageiro.mensagemLida<char>() == 'c');
00340 } catch(IPC::Erro& erro) {
00341 cerr << string(erro) << endl;
00342 assert(false);
00343 }
00344 }
00345
00346 #endif // TESTE