simple_tcp_server.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /**
  2. * Simple multi-thread/multi-core TCP server.
  3. *
  4. */
  5. package main
  6. import (
  7. "flag"
  8. "net"
  9. "fmt"
  10. "syscall"
  11. )
  12. const maxRead = 25
  13. func main() {
  14. flag.Parse()
  15. if flag.NArg() != 2 {
  16. panic("usage: host port")
  17. }
  18. hostAndPort := fmt.Sprintf("%s:%s", flag.Arg(0), flag.Arg(1))
  19. listener := initServer(hostAndPort)
  20. for {
  21. conn, err := listener.Accept()
  22. checkError(err, "Accept: ")
  23. go connectionHandler(conn)
  24. }
  25. }
  26. func initServer(hostAndPort string) *net.TCPListener {
  27. serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)
  28. checkError(err, "Resolving address:port failed: `" + hostAndPort + "'")
  29. listener, err := net.ListenTCP("tcp", serverAddr)
  30. checkError(err, "ListenTCP: ")
  31. println("Listening to: ", listener.Addr().String())
  32. return listener
  33. }
  34. func connectionHandler(conn net.Conn) {
  35. connFrom := conn.RemoteAddr().String()
  36. println("Connection from: ", connFrom)
  37. sayHello(conn)
  38. for {
  39. var ibuf []byte = make([]byte, maxRead + 1)
  40. length, err := conn.Read(ibuf[0:maxRead])
  41. ibuf[maxRead] = 0 // to prevent overflow
  42. switch err {
  43. case nil:
  44. handleMsg(length, err, ibuf)
  45. case syscall.EAGAIN: // try again
  46. continue
  47. default:
  48. goto DISCONNECT
  49. }
  50. }
  51. DISCONNECT:
  52. err := conn.Close()
  53. println("Closed connection: ", connFrom)
  54. checkError(err, "Close: ")
  55. }
  56. func sayHello(to net.Conn) {
  57. obuf := []byte{'L', 'e', 't', '\'', 's', ' ', 'G', 'O', '!', '\n'}
  58. wrote, err := to.Write(obuf)
  59. checkError(err, "Write: wrote " + string(wrote) + " bytes.")
  60. }
  61. func handleMsg(length int, err error, msg []byte) {
  62. if length > 0 {
  63. print("<", length, ":")
  64. for i := 0; ; i++ {
  65. if msg[i] == 0 {
  66. break
  67. }
  68. fmt.Printf("%c", msg[i])
  69. }
  70. print(">")
  71. }
  72. }
  73. func checkError(error error, info string) {
  74. if error != nil {
  75. panic("ERROR: " + info + " " + error.Error()) // terminate program
  76. }
  77. }