Академический Документы
Профессиональный Документы
Культура Документы
Abril 2009
Roteiro
● Introdução
● Objetivos
● Exemplo
● Considerações Finais
Introdução
● Estratégias de Concorrência para Servidores
como atender a múltiplos clientes
simultaneamente
● Mecanismos de Concorrência em POSIX
como ler e escrever de/para múltiplos
dispositivos de I/O simultaneamente
● Mecanismos de Abstração em C++0x
podemos utilizar abstrações mais
confortáveis para tratar os problemas acima
Objetivos
● Desenvolver um binding POSIX/C++ para sockets
– Interface mais “limpa”:
● orientação a objetos
● programação genérica
● uma implementação de referência
● Propor um padrão para projeto de servidores
concorrentes em C++
– Estratégias de concorrência
– Servidores concorrentes genéricos
– Handlers genéricos
– Implementação de referência
POSIX/C Sockets
● POSIX é uma norma que especifica a interface de
programação entre sistema operacional e
programas de usuário
● POSIX/C é POSIX na linguagem C
● Sockets são dispositivos para comunicação entre
processos
● A programação de servidores concorrentes
utilizando sockets em C possui limitações:
– verificação tediosa de erros
– informação com mínima tipagem
– ..?
POSIX/C Sockets
struct addrinfo hint =
{ AI_PASSIVE, AF_INET, SOCK_STREAM, 0, 0, 0, 0,
0 };
struct addrinfo* ai;
int st = getaddrinfo("", "echo", &hint, &ai);
if (st != 0) {
fprintf(stderr, "%s\n", gai_strerror(status));
exit(1);
}
sockaddr_storage addr;
memcpy(&addr, ai->ai_addr, ai->ai_addrlen);
socklen_t addrlen = ai->ai_addrlen;
freeaddrinfo(ai);
POSIX/C Sockets
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(7);
addr.sin_addr.s_addr = htonl(IPADDR_ANY);
socklen_t addrlen = sizeof(sockaddr_in);
POSIX/C Sockets
int listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener == -1) {
perror(NULL);
exit(1);
}
st = listen(listener, SOMAXCONN);
if (status == -1) {
perror(NULL);
exit(1);
}
POSIX/C Sockets
is_running = 1;
while (is_running) {
int client = accept(listener, NULL, 0);
if (client == -1) {
perror(NULL);
exit(1);
}
echo_handler(client);
}
close(listener);
C++0x
C++ é C
com melhores mecanismos de abstração
socket ();
socket (int family, int socktype, int protocol =
0);
~socket ();
// etc.
};
C++0x
class socket {
void
listen (int backlog = SOMAXCONN);
socket
accept ();
};
POSIX/C++ Sockets
addrinfo hint =
{ AI_PASSIVE, AF_INET, SOCK_STREAM, 0, 0, 0, 0,
0 };
sockaddr_storage addr;
memcpy(&addr, ai.ai_addr, ai.ai_addrlen);
POSIX/C++ Sockets
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(7);
addr.sin_addr.s_addr = htonl(IPADDR_ANY);
POSIX/C++ Sockets
posix::socket listener(AF_INET, SOCK_STREAM);
listener.bind(addr);
listener.listen();
is_running = 1;
while (is_running) {
echo_handler(std::move(client));
}
POSIX/C++ Sockets
● O que ganhei com o Binding?
● Exceções propagam erros automaticamente; o
responsável que capture e trate
● Notação mais elegante economiza argumentos em
chamadas
● Gerência de recursos evita vazamentos
● Programação Genérica sugere reuso...
– agora com uma classe socket reusável, o que seria uma
classe servidor reusável?
Servidor Genérico
● Um template de classes é uma regra
para geração mecânica de classes
● Uma classe genérica é uma meta-classe,
especializável por outras classes,
que definem seu comportamento
● Uma estratégia é reaplicável,
assim como uma meta-classe...
● ...em tempo de compilação, não de execução.
Servidor Genérico: Modelo
Servidor Genérico: Modelo
●
server encapsula o modo de uso de um
mecanismo de concorrência qualquer
●
StrategyServer especifica a relação entre
server e StrategyHandlers
●
foo_handler implementa o protocolo de
aplicação foo, obedecendo a StrategyHandler
●
server<foo_handler> gera mecanicamente
classes servidor-do-protocolo-foo
Servidor Genérico: Estratégia
● Inicialmente, um loop: uma iteração, um cliente
● Concorrência com threads ou processos:
iteração/cliente inicia novo
● thread
● processo
● Concorrência com notificação de
disponibilidade:
um “demultiplexador” mantém múltiplos clientes
● select
● poll
Servidor Genérico: Aplicação
addrinfo hint =
{ AI_PASSIVE, AF_INET, SOCK_STREAM, 0, 0, 0, 0,
0 };
auto result = posix::getaddrinfo("", "echo", hint);
server.configure(*result.begin());
server.start();