Skip to content

Instantly share code, notes, and snippets.

@kehiy
Last active June 25, 2023 17:48
Show Gist options
  • Save kehiy/15b5595414d51d84f9e114df43d6f81a to your computer and use it in GitHub Desktop.
Save kehiy/15b5595414d51d84f9e114df43d6f81a to your computer and use it in GitHub Desktop.
Custom TCP Server In Golang
package main
import (
"fmt"
"log"
"net"
)
type Message struct {
from string
payload []byte
}
type Server struct {
listenAddr string
ln net.Listener
quitch chan struct{}
msgch chan Message
}
// make a new server
func newServer(listenAddr string) *Server {
return &Server{
listenAddr: listenAddr,
quitch: make(chan struct{}),
msgch: make(chan Message, 10),
}
}
// start listening to address
func (s *Server) start() error {
ln, err := net.Listen("tcp", s.listenAddr)
if err != nil {
return err
}
defer ln.Close()
s.ln = ln
go s.acceptLoop()
<-s.quitch
// close message channel after stopping server
close(s.msgch)
return nil
}
func (s *Server) acceptLoop() {
for {
conn, err := s.ln.Accept()
if err != nil {
//* we are just log the error and continue to accepting new connections
fmt.Println("accept error:", err)
continue
}
go s.readLoop(conn)
}
}
func (s *Server) readLoop(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 2048)
for {
n, err := conn.Read(buf)
if err != nil {
fmt.Println("read error:", err)
continue
}
// msg := buf[:n]
// fmt.Println(string(msg))
s.msgch <- Message{
from: conn.RemoteAddr().String(),
payload: buf[:n],
}
//* write a response to connection
conn.Write([]byte("your message recived!\n"))
}
}
func main() {
server := newServer(":2952")
go func() {
for msg := range server.msgch {
fmt.Printf("recived new from connection(%s): %s\n", msg.from, msg.payload)
}
}()
log.Fatal(server.start())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment