Cliente e servidor socket em Golang com tratamento de sinais.

Continuando nossa série de artigos sobre cliente/servidor, adicionaremos um novo canal no exemplo anterior. Esse canal tratará sinais enviados pelo sistema operacional.

O sistema operacional envia sinais aos programas para gerenciar processos. Por exemplo, ao pressionar Ctrl+C, o sistema operacional envia o sinal SIGINT, informando o programa que o usuário deseja interrompê-lo.

Por padrão, o programa é fechado. Porém, podemos interceptar esse sinal e agir conforme necessário. Neste caso, apenas finalizaremos o programa. Em sistemas reais, esse recurso pode ser usado para salvar informações antes de fechar, encerrar outros processos, fechar conexões e arquivos, entre outros. Esse processo é conhecido como graceful shutdown.

Servidor

No servidor, criamos um canal e informamos ao sistema para enviar sinais por esse canal. Também criamos uma goroutine para monitorar o canal.

sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

go func() {
	<-sigs
	fmt.Println("\nShutdown server...")
	os.Exit(0)
}()

Cliente

No cliente, a abordagem é diferente. Não precisamos criar uma goroutine. Como já estamos utilizando select case para tratar canais, basta adicionar o novo canal aos cases existentes. Ele será tratado normalmente, assim como os outros canais.

sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

for {
	select {
	case <-sigs:
		fmt.Println("\nDisconnecting...")
		conn.Close()
		os.Exit(0)
		...

Código-fonte

Confira o código-fonte do nosso servidor e cliente:

Vídeos com explicação

Conclusão

A alteração para adicionar o tratamento de sinais foi simples, mas essencial. Ao fechar o programa, é importante garantir que ele esteja em um estado consistente. Por exemplo, se o programa salva dados em um banco de dados, é recomendável esperar que as transações abertas sejam concluídas antes de encerrar o programa.

Cesar Gimenes

Última modificação