[Golang]Socket編程01----實現基本功能的Client和Server

支持多鏈接。git

Server運行以後,進入Accept阻塞狀態。Accept獲得一個Conn以後,開啓一個協程,分別有兩個協程阻塞在Read和Write。當Read一個數據以後,將Read獲得的數據寫入readChannel中,以後再對其進行處理。在writeChannel獲得一個數據以後,向Conn寫入數據。app

Client運行後,接入Server,以後開啓兩個協程阻塞在Read和Write的Channel中。在Scan獲得一個數據以後,向writeChannel寫入數據,喚醒阻塞的協程向Conn中寫入數據。當Server中有數據返回時,read協程被喚醒,將數據寫入readChannel中。socket

 

固然,還有諸多細節要處理。好比Conn的關閉在何時等等。tcp

 

客戶端源碼.net

package client

import (
	"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 string
		fmt.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))
		}
	}
}

服務端代碼:unix

package server

import (
	"net"
	"git.oschina.net/sdlszjb/unix_socket/errs"
	"fmt"
)

var client_num int = 0

func 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)

}
相關文章
相關標籤/搜索