This is a creation in Article, where the information may have evolved or changed.
Implementing logic
1, Golang version 1.3
2, the realization principle:
1, the main process to establish a TCP monitoring service, and initialize a variable Talkchan: = Make (Map[int]chan string)
2, when the main process accept connection request, use go to start a process A to maintain the connection with the client, bring Taokchan into the co-thread
3, and the client to establish a connection to the process a, send a message to the client, so that it sends its own user information.
4. After receiving the user information sent by the client, we establish a pipeline for this user Talkchan[uid] = make (Chan string)
5, co-process A and then start a co-A1 to read the message sent by the client, and to determine who is sent to the message, and then put the message to the corresponding Chan.
6, the co-process A and then start a A2 to read this user's corresponding pipeline, if there is information, then take out to send to the client.
Implementation code
Service-side test code: SERVER.GO
Package Mainimport ("FMT" "Log" "Net" "StrConv") func handleconnection (conn net. Conn, Talkchan Map[int]chan string) {//fmt. Printf ("%p\n", Talkchan)//used to check if the pointer is passed/* Defines the current user's Uid*/var curuid intvar err error/* define close channel */var closed = make (chan bool) d Efer func () {fmt. Println ("defer do:conn closed") Conn. Close () fmt. Printf ("delete userid [%v] from Talkchan", Curuid) Delete (Talkchan, Curuid)} ()/** * Prompts the user to set their own UID, if not set, does not execute */for {//prompt The client sets the user id_, err = conn. Write ([]byte ("Set user UID")) if err! = Nil {return}data: = make ([]byte, 1024x768) c, err: = conn. Read (data) if err! = Nil {//closed <-true//this will block | Back the For loop that takes closed, not executed to. Return}suid: = string (Data[0:c])//turn to the INT type UID, _: = StrConv. Atoi (SUid) if UID < 1 {continue}curuid = Uidtalkchan[uid] = make (Chan string)//fmt. PRINTLN (Conn, "has set UID", UID, "can Talk") _, Err = conn. Write ([]byte ("has set UID" +suid+ "can Talk")) if err! = Nil {return}break}fmt. Println ("Err 3")//Current all connections to FMT. PRINTLN (Talkchan)//Read the data sent by the client to go func () {for {//Read client data sent overKe ([]byte, 1024x768) c, err: = conn. Read (data) if err! = Nil {fmt. Println ("Have no client write", err) closed <-true//Can be used here | Because it was handled with a new thread of go. | Even if Chan blocks, the back will execute to read closed this chan}clientstring: = String (Data[0:c])//Send the client data, write to the corresponding Chan if Curuid = = 3 {talkchan[4] <-clientstring} else {talkchan[3] <-clientstring}}} ()/* Read the data from Chan to the client and write it to the client */go func () {for {talkstring}: = <-talkchan[curuid]_, err = conn. Write ([]byte (talkstring)) if err! = Nil {closed <-true}}} ()/* Check whether the connection is closed if it is closed then eject the thread to execute the defer statement */for {if <-closed {return}}} Func Main () {/** establishes a listener link */ln, err: = Net. Listen ("TCP", "127.0.0.1:6010") if err! = Nil {panic (err)}//Create a pipeline//talkchan: = Map[f]talkchan: = Make (Map[int]chan String) fmt. Printf ("%p\n", Talkchan)/* Listens if there is a connection request coming from the client */for {FMT. PRINTLN ("Wait Connect ...") conn, err: = ln. Accept () if err! = Nil {log. Fatal ("Get Client Connection Error:", err)}go handleconnection (conn, Talkchan)}}
Client Test code: Client.go
Package Mainimport ("FMT" "Math/rand" "NET") Func main () {conn, err: = Net. Dial ("TCP", "127.0.0.1:6010") if err! = Nil {panic (err)}fmt. fprintf (conn, "Hello server\n") defer Conn. Close () go writefromserver (conn) for {var talkcontent stringfmt. SCANLN (&talkcontent) If Len (talkcontent) > 0 {_, err = conn. Write ([]byte (talkcontent)) if err! = Nil {fmt. Println ("Write to Server Error") Return}}}}func Connect () {conn, err: = Net. Dial ("TCP", "127.0.0.1:6010") if err! = Nil {panic (err)}fmt. fprintf (conn, "Hello server\n") defer Conn. Close () go writefromserver (conn) for {var talkcontent stringfmt. SCANLN (&talkcontent) If Len (talkcontent) > 0 {_, err = conn. Write ([]byte (talkcontent)) if err! = Nil {fmt. Println ("Write to Server Error") Return}}}}func Writefromserver (conn net. Conn) {defer Conn. Close () for {data: = make ([]byte, 1024x768) c, err: = conn. Read (data) if err! = Nil {fmt. PRINTLN ("Rand", Rand.) INTN (+), "have no server write", err) return}fmt. Println (String (data[0:c]) + "\ n")}}