Implementation logic
1. Golang version 1.3
2. Implementation principle:
1. The main process establishes a TCP listening service and initializes a variable talkChan := make(map[int]chan string)
2. After the main process ACCEPT connection request, use go to start a coroutine A to maintain the connection with the client, and bring taokChan into the coroutine.
3. Coroutine A that establishes a connection with the client and sends a message to the client to send its own user information.
4. After receiving the user information sent by the client, coroutine A creates a pipeline corresponding to this user talkChan[uid] = make(chan string)
5. Coroutine A starts a coroutine A1 to read the message sent by the client and use it to determine who the message was sent to, and then put the message in the corresponding chan.
6. Coroutine A starts another coroutine A2 to read the corresponding pipeline of this user. If there is information in it, it will be taken out and sent to the client.
Implement code
Server test code:
package main
import (
"fmt"
"log"
"net"
"strconv"
)
func handleConnection(conn , talkChan map[int]chan string) {
//("%p\n", talkChan) // Used to check whether it is a pointer passed
/*
Define the uid of the current user
*/
var curUid int
var err error
/*
Define a closed channel
*/
var closed = make(chan bool)
defer func() {
("defer do : conn closed")
()
("delete userid [%v] from talkChan", curUid)
delete(talkChan, curUid)
}()
/**
* Prompt the user to set his own uid. If it is not set, it will not execute it facing downwards.
*/
for {
//Prompt the client to set the user id
_, err = ([]byte("Please set user uid"))
if err != nil {
return
}
data := make([]byte, 1024)
c, err := (data)
if err != nil {
//closed <- true //This will block | The closed for loop is taken later and it is not executed.
return
}
sUid := string(data[0:c])
//Convert to int type
uid, _ := (sUid)
if uid < 1 {
continue
}
curUid = uid
talkChan[uid] = make(chan string)
//(conn, "have set uid ", uid, "can talk")
_, err = ([]byte("have set uid "+sUid+" can talk"))
if err != nil {
return
}
break
}
("err 3")
//All current connections
(talkChan)
//Read the data transmitted from the client
go func() {
for {
//Read the data transmitted from the client continuously
data := make([]byte, 1024)
c, err := (data)
if err != nil {
("have no client write", err)
closed <- true //You can use | because it is processed with the newly opened thread used by go. | Even if the chan is blocked, the subsequent ones will be executed to read the closed chan
}
clientString := string(data[0:c])
//Write the data from the client into the corresponding chan
if curUid == 3 {
talkChan[4] <- clientString
} else {
talkChan[3] <- clientString
}
}
}()
/*
Read the data to this client from chan and write it to the client
*/
go func() {
for {
talkString := <-talkChan[curUid]
_, err = ([]byte(talkString))
if err != nil {
closed <- true
}
}
}()
/*
Check whether the connection has been closed. If it is closed, the thread will be pushed out. Execute the defer statement
*/
for {
if <-closed {
return
}
}
}
func main() {
/**
Create a listening link
*/
ln, err := ("tcp", "127.0.0.1:6010")
if err != nil {
panic(err)
}
//Create a pipeline
//talkChan := map[f]
talkChan := make(map[int]chan string)
("%p\n", talkChan)
/*
Listen to whether there are connection requests from clients
*/
for {
("wait connect...")
conn, err := ()
if err != nil {
("get client connection error: ", err)
}
go handleConnection(conn, talkChan)
}
}
Client test code:
package main
import (
"fmt"
"math/rand"
"net"
)
func main() {
conn, err := ("tcp", "127.0.0.1:6010")
if err != nil {
panic(err)
}
(conn, "hello server\n")
defer ()
go writeFromServer(conn)
for {
var talkContent string
(&talkContent)
if len(talkContent) > 0 {
_, err = ([]byte(talkContent))
if err != nil {
("write to server error")
return
}
}
}
}
func connect() {
conn, err := ("tcp", "127.0.0.1:6010")
if err != nil {
panic(err)
}
(conn, "hello server\n")
defer ()
go writeFromServer(conn)
for {
var talkContent string
(&talkContent)
if len(talkContent) > 0 {
_, err = ([]byte(talkContent))
if err != nil {
("write to server error")
return
}
}
}
}
func writeFromServer(conn ) {
defer ()
for {
data := make([]byte, 1024)
c, err := (data)
if err != nil {
("rand", (10), "have no server write", err)
return
}
(string(data[0:c]) + "\n ")
}
}