這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
支援多串連。
Server運行之後,進入Accept阻塞狀態。Accept得到一個Conn之後,開啟一個協程,分別有兩個協程阻塞在Read和Write。當Read一個資料之後,將Read得到的資料寫入readChannel中,之後再對其進行處理。在writeChannel得到一個資料之後,向Conn寫入資料。
Client運行後,接入Server,之後開啟兩個協程阻塞在Read和Write的Channel中。在Scan得到一個資料之後,向writeChannel寫入資料,喚醒阻塞的協程向Conn中寫入資料。當Server中有資料返回時,read協程被喚醒,將資料寫入readChannel中。
當然,還有諸多細節要處理。比如Conn的關閉在什麼時候等等。
用戶端源碼
package clientimport ("net""git.oschina.net/sdlszjb/unix_socket/errs""fmt")func StartClient1() {tcpAddress, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:1300")if err != nil {errs.Error_exit(err)}conn, err := net.DialTCP("tcp", nil, tcpAddress)if err != nil {errs.Error_exit(err)}writeChan := make(chan []byte, 1024)readChan := make(chan []byte, 1024)go writeConnection(conn, writeChan)go readConnection(conn, readChan)//go handleReadChannel(readChan)for {var s stringfmt.Scan(&s)writeChan <- []byte(s)}}func readConnection(conn *net.TCPConn, channel chan []byte) {defer conn.Close()buffer := make([]byte, 2048)for {n, err := conn.Read(buffer)if err != nil {errs.Error_print(err)return}println("Received from:", conn.RemoteAddr(), string(buffer[:n]))//channel <- buffer[:n]}}func writeConnection(conn *net.TCPConn, channel chan []byte) {defer conn.Close()for {select {case data := <- channel:_, err := conn.Write(data)if err != nil {errs.Error_exit(err)}println("Write to:", conn.RemoteAddr(), string(data))}}}
服務端代碼:
package serverimport ("net""git.oschina.net/sdlszjb/unix_socket/errs""fmt")var client_num int = 0func StartServer1() {l, err := net.Listen("tcp", ":1300")if err != nil {errs.Error_exit(err)}defer l.Close()for {conn, err := l.Accept()if err != nil {errs.Error_print(err)continue}client_num++fmt.Printf("A new Connection %d.\n", client_num)go handlerConnection(conn)}}func handlerConnection(conn net.Conn) {defer closeConnection(conn)readChannel := make(chan []byte, 1024)writeChannel := make(chan []byte, 1024)go readConnection(conn, readChannel)go writeConnection(conn, writeChannel)for {select {case data := <- readChannel:if string(data) == "bye" {return}writeChannel <- append([]byte("Back"), data...)}}}func writeConnection(conn net.Conn, channel chan []byte) {for {select {case data := <- channel:println("Write:", conn.RemoteAddr().String(), string(data))_, err := conn.Write(data)if err != nil {errs.Error_print(err)return}}}}func readConnection(conn net.Conn, channel chan []byte) {buffer := make([]byte, 2048)for {n, err := conn.Read(buffer)if err != nil {errs.Error_print(err)channel <- []byte("bye")//這裡須要進一步改進!break}println("Recei:", conn.RemoteAddr().String(), string(buffer[:n]))channel <- buffer[:n]}}func closeConnection(conn net.Conn) {conn.Close()client_num--fmt.Printf("Now, %d connections is alve.\n", client_num)}