server.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package tcp
  2. import (
  3. "context"
  4. "net"
  5. "os"
  6. "os/signal"
  7. "sync"
  8. "syscall"
  9. "github.com/runningwater/go-redis/interface/tcp"
  10. "github.com/runningwater/go-redis/lib/logger"
  11. )
  12. type Config struct {
  13. Address string
  14. }
  15. func ListenAndServeWithSignal(cfg *Config, handler tcp.Handler) error {
  16. closeChan := make(chan struct{})
  17. sigChan := make(chan os.Signal, 1)
  18. signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) //nolint:govt
  19. go func() {
  20. sig := <-sigChan
  21. switch sig {
  22. case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
  23. closeChan <- struct{}{}
  24. }
  25. }()
  26. listener, err := net.Listen("tcp", cfg.Address)
  27. if err != nil {
  28. return err
  29. }
  30. logger.Info("start listening at", cfg.Address)
  31. return ListenAndServe(listener, handler, closeChan)
  32. }
  33. func ListenAndServe(listener net.Listener, handler tcp.Handler, closeChan <-chan struct{}) error {
  34. go func() {
  35. <-closeChan
  36. logger.Info("shutting down...")
  37. _ = listener.Close()
  38. _ = handler.Close()
  39. }()
  40. defer func() {
  41. _ = listener.Close()
  42. _ = handler.Close()
  43. }()
  44. ctx := context.Background()
  45. var waitDone sync.WaitGroup
  46. for {
  47. conn, err := listener.Accept()
  48. if err != nil {
  49. break
  50. }
  51. logger.Info("accept link")
  52. waitDone.Add(1)
  53. go func() {
  54. defer func() {
  55. waitDone.Done()
  56. }()
  57. handler.Handle(ctx, conn)
  58. }()
  59. } // end for
  60. waitDone.Wait()
  61. return nil
  62. }