ما میتوانیم در گو با استفاده از کتابخانه net یک سرور tcp ایجاد کنیم
بعد از تکمیل شدن سرور با استفاده از دستور telnet
به آن متصل میشویم
در قطعه کد زیر
با تابع acceptLoop()
درخواست های اتصال را مپذیریم
و با تابع readLoop()
پیام های اتصال را میخوانیم
1package main
2
3import (
4 "fmt"
5 "log"
6 "net"
7)
8
9// ساختار هر پیام در سرور
10type Message struct {
11 // ادرس ip ارسال کننده پیام
12 from string
13 // متن و محتوای پیام
14 payload []byte
15}
16
17// ساختار سرور
18type Server struct {
19 // ادرس و یا پورت سرور
20 listenAddr string
21 // listener
22 ln net.Listener
23 // چنل پیام برای انتقال پیام های دریافتی از اتصال ها بین گوروتین ها
24 msgch chan Message
25}
26
27// ایجاد یک سرور جدید
28func newServer(listenAddr string) *Server {
29 return &Server{
30 listenAddr: listenAddr,
31 msgch: make(chan Message, 10),
32 }
33}
34
35// شروع سرور و دریافت اتصال های جدید
36func (s *Server) start() error {
37 // شروع سرور
38 ln, err := net.Listen("tcp", s.listenAddr)
39 if err != nil {
40 return err
41 }
42 defer ln.Close()
43 // مقدار دهی listener
44 s.ln = ln
45 // با تابع acceptLoop اتصال های جدید به سرور را مدیریت میکنیم
46 // با استفاده از go هر اتصال را روی یک گوروتین مجزا مدیریت میکنیم
47 go s.acceptLoop()
48
49 return nil
50}
51
52func (s *Server) acceptLoop() {
53 for {
54 // اتصال های موجود را تایید میکنیم متغییر conn را با اتصال مورد نظر مقدار دهی میکنیم
55 conn, err := s.ln.Accept()
56 if err != nil {
57 fmt.Println("accept error:", err)
58 continue
59 }
60 // با استفاده از این تابع مقادیر ارسال شده توسط اتصال را به چنل message میدهیم
61 go s.readLoop(conn)
62 }
63}
64
65func (s *Server) readLoop(conn net.Conn) {
66 defer conn.Close()
67 buf := make([]byte, 2048)
68
69 for {
70 // پیام ارسال شده توسط هر اتصال را به متغییر buf میدهیم
71 n, err := conn.Read(buf)
72 if err != nil {
73 fmt.Println("read error:", err)
74 continue
75 }
76
77 s.msgch <- Message{
78 // ادرس ip ارسال کننده پیام از نوع net.IP
79 from: conn.RemoteAddr().String(),
80 // متن پیام
81 payload: buf[:n],
82 }
83
84 // بعد از دریافت هر پیام یک پیام به عنوان پاسخ ارسال میکنیم
85 conn.Write([]byte("your message recived!\n"))
86 }
87}
88
89func main() {
90 // ساخت سرور
91 server := newServer(":3000")
92
93 go func() {
94 // در ازای هر پیام مقادیر آن را چاپ میکنیم
95 for msg := range server.msgch {
96 fmt.Printf("recived new from connection(%s): %s\n", msg.from, msg.payload)
97 }
98 }()
99
100 // شروع سرور
101 log.Fatal(server.start())
102
103}
بعد از پایان پیاده سازی سرور tcp
با دستور زیر سرور خود را اجرا میکنیم:
go run main.go
و با دستور زیر در یک ترمینال مجزا به سرور متصل میشویم:
telnet localhost 3000
حال با نوشتن پیام و ارسال آن در ترمینال telnet
متن پیام و ادرس اتصال در ترمینال سرور قابل مشاهده است.
توجه داشته باشید که دستور telnet
در ویندوز نیاز به فعال سازی دارد.