Continuando a explorar o assunto do post passado, sobre sockets em Caché, vamos explorar outra possibilidade.
No post passado, mostrei um exemplo simples de como fazer para criar sockets, tanto do lado servidor, quanto do lado cliente. Entretanto, aquele exemplo tinha uma grande limitação: na parte do servidor, o código aceitava somente uma requisição depois encerrava. Como exemplo é válido, mas num cenário real, é muito limitador.
Entretanto, o objeto %IO.ServerSocket possui outro método, que nos permite deixar o socket servidor mais parecido com um ServerSocket em java. Este método é o ListenJob
.
Antes de mais nada, vamos ver como fica um código simples:
Class teste.ServerSpawnSocket Extends %RegisteredObject
{
ClassMethod server()
{
set sock = ##class(%IO.ServerSocket).%New()
set st = $$$OK
w "Starting server...", !
// open serverSocket, param:
// port, timeOut, status
w sock.Open(7777, -1, st), !
w st, !
// server to listen incoming connections,
// and when it arrives, spawns a new job in background
// params:
//
// timeOut,
// classNameContainingMethodToBeCalled,
// jobArguments,
// socketClassName (default: %IO.ServerSocket),
// maxNumberOfJobs (default: -1),
// runInForeground (default: 0 - no),
// status
w sock.ListenJob(-1, "teste.ServerSpawnSocket", "", , , , st), !
w st, !
w "Closing server...", !
quit
}
//===================================================
ClassMethod OnConnected(StreamHandler As %IO.DeviceStream, AnotherArgs)
{
set st = $$$OK
// reading from socket, param:
// maxStringSize, timeout, status, lineTerminator
set ^someVar("read from tcp") = StreamHandler.ReadLine(50, 30, st, $c(13))
// writing to socket, param:
// stringToBeWritten, automaticFlush, status
d StreamHandler.Write("Goodbye Dolly", 1, st)
d StreamHandler.Close(st)
set ^someVar("status") = st
quit
}
}
O método server()
é bem simples, tendo mais linhas de comentário do que propriamente código =P. Depois de criado o objeto, chamamos novamente o método open
deste, definindo em que porta o socket ficará escutando. O método que mais nos interessa agora, é o seguinte, ListenJob
.
Este método executa o seguinte: ao chegar nova requisição no socket, se não houver restrição ao endereço da requisição, o método cria um novo job (processo) que rodará em background, passando como parâmetro, um objeto %IO.DeviceStream, que contém a stream (fluxo) de dados criado pelo socket. Mas qual método o Caché invoca? Bem, depois de passear pelo código-fonte do %IO.ServerSocket, descubro que depois de invocar alguns métodos internos da própria classe, o objeto invoca o método de classe (em Java, seria um método static
) OnConnected
, da classe passada como segundo parâmetro na chamada de ListenJob
.
O ListenJob
ainda pode controlar o número máximo de jobs simultâneos, que é o quinto parâmetro. O primeiro parâmetro é o conhecido timeout, que se passado -1, nunca expira. O terceiro parâmetro pode ser composto de uma lista, contendo parâmetros adicionais a serem passados para o método OnConnected
. O sexto parâmetro é inútil (mais sobre isso em um futuro post), e o último parâmetro é o conhecido objeto que retorna o status da execução do método.
No exemplo, pode-se ver que foi passado como parâmetro o nome da própria classe, mas poderia muito bem ser outra qualquer. O importante é que a classe passada contenha o método OnConnected
, cuja assinatura pode ser vista no exemplo (IMPORTANTE: essa assinatura não é fixa, nem definitiva, muito menos oficial, já que na documentação não consta nada disso - pelo menos eu não achei em lugar algum, se você leitor, sabe onde está, deixe um comentário dizendo, por favor).
Dentro do método OnConnected
, manipulamos a stream de dados como quisermos, o exemplo simplesmente lê algo da stream, jogando em uma variável global, e escreve algo na stream, antes de fechar a conexão.
Se foi ou não proveitoso o exemplo, deixe um comentário aqui embaixo.
segunda-feira, 23 de julho de 2007
Ainda Sockets em Caché - ServerSockets
Postado por
Andarilho
às
11:49
Marcadores: caché, programação, rede, sockets
Assinar:
Postar comentários (Atom)
Nenhum comentário:
Postar um comentário