Implementation logic
1, Golang version 1.3
2. Principle of realization:
1. The main process establishes the TCP listening service and initializes a variable Talkchan: = Make (Map[int]chan string)
2, when the main process accept connection request, use go to start a coprocessor to maintain the connection with the client, the Taokchan into the association Chengri
3, and the client to establish a connection to the coordination of 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, the co-process a establishes a corresponding pipeline talkchan[uid] = make (Chan string)
5, the process A and then start a A1 to read the message sent by the client, and to determine who is sent to the message, and then put the message in the corresponding Chan.
6, coprocessor A and then start a A2 to read this user's corresponding pipe, if there is information, then take out to send to the client.
Implementation code
Service-side test code: SERVER.GO
Copy Code code as follows:
Package Main
Import (
"FMT"
"Log"
"NET"
"StrConv"
)
Func handleconnection (Conn net. Conn, Talkchan Map[int]chan string) {
Fmt. Printf ("%p\n", Talkchan)//To check whether the pointer is passed over
/*
Defines the UID of the current user
*/
var curuid int
var err error
/*
Define close Channel
*/
var closed = make (chan bool)
Defer func () {
Fmt. Println ("defer do:conn closed")
Conn. Close ()
Fmt. Printf ("delete userid [%v] from Talkchan", Curuid)
Delete (Talkchan, curuid)
}()
/**
* Prompt the user to set their UID, if not set, then do not face down
*/
for {
Prompt client to set user ID
_, Err = conn. Write ([]byte ("Please set user UID")
If Err!= nil {
Return
}
Data: = Make ([]byte, 1024)
C, ERR: = conn. Read (data)
If Err!= nil {
Closed <-true//this will block | followed by a closed for loop that was not executed to.
Return
}
SUid: = string (Data[0:c])
turn to int type
UID, _: = StrConv. Atoi (SUid)
If UID < 1 {
Continue
}
Curuid = UID
Talkchan[uid] = make (Chan string)
Fmt. PRINTLN (conn, "have set UID", UID, "can Talk")
_, Err = conn. Write ([]byte ("have set UID" +suid+ "can Talk"))
If Err!= nil {
Return
}
Break
}
Fmt. Println ("Err 3")
All current Connections
Fmt. Println (Talkchan)
/Read data from client
go func () {
for {
//Non-stop reading of data from client
Data: = Make ([]byte, 1024)
C, ERR: = conn. Read (data)
If err!= nil {
FMT. Println ("Have no client write", err)
closed <-true//Can be used here | Because it is handled with a new thread on the go. | even if Chan is blocked, the back will execute to read closed this Chan
}
Clientstring: = string (Data[0:c])
The data from the client is written 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 to see if the connection has been closed if closed then eject the thread to execute the defer statement
*/
for {
If <-closed {
Return
}
}
}
Func Main () {
/**
Establish a listening link
*/
ln, ERR: = Net. Listen ("TCP", "127.0.0.1:6010")
If Err!= nil {
Panic (ERR)
}
Create a pipe
Talkchan: = Map[f]
Talkchan: = Make (Map[int]chan string)
Fmt. Printf ("%p\n", Talkchan)
/*
Listen for a connection request 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
Copy Code code as follows:
Package Main
Import (
"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 string
Fmt. 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 string
Fmt. 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, 1024)
C, ERR: = conn. Read (data)
If Err!= nil {
Fmt. PRINTLN ("Rand", Rand.) Intn (a), "have no server write", err)
Return
}
Fmt. Println (String (data[0:c]) + "\ n")
}
}