1. 程式人生 > >Go語言簡單的TCP程式設計

Go語言簡單的TCP程式設計


package main

import(
	"fmt"
	"os"
	"net"
)

////////////////////////////////////////////////////////
//
//錯誤檢查
//
////////////////////////////////////////////////////////
func checkError(err error,info string) (res bool) {
	
	if(err != nil){
		fmt.Println(info+"  " + err.Error())
		return false
	}
	return true
}

////////////////////////////////////////////////////////
//
//伺服器端接收資料執行緒
//引數:
//		資料連線 conn
//		通訊通道 messages
//
////////////////////////////////////////////////////////
func Handler(conn net.Conn,messages chan string){
	
	fmt.Println("connection is connected from ...",conn.RemoteAddr().String())
	
	buf := make([]byte,1024)
	for{
		lenght, err := conn.Read(buf)
		if(checkError(err,"Connection")==false){
			conn.Close()
			break
		}
		if lenght > 0{
			buf[lenght]=0
		}
		//fmt.Println("Rec[",conn.RemoteAddr().String(),"] Say :" ,string(buf[0:lenght]))
		reciveStr :=string(buf[0:lenght])
		messages <- reciveStr
			
	}
		
}

////////////////////////////////////////////////////////
//
//伺服器傳送資料的執行緒
//
//引數
//		連線字典 conns
//		資料通道 messages
//
////////////////////////////////////////////////////////
func echoHandler(conns *map[string]net.Conn,messages chan string){
	
	
	for{
		msg:= <- messages
		fmt.Println(msg)
		
		for key,value := range *conns {
			
			fmt.Println("connection is connected from ...",key)
			_,err :=value.Write([]byte(msg))
			if(err != nil){
				fmt.Println(err.Error())
				delete(*conns,key)
			}
			
		}
	}
	
}


////////////////////////////////////////////////////////
//
//啟動伺服器
//引數
//	埠 port
//
////////////////////////////////////////////////////////
func StartServer(port string){
		service:=":"+port //strconv.Itoa(port);
		tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
		checkError(err,"ResolveTCPAddr")
		l,err := net.ListenTCP("tcp",tcpAddr)
		checkError(err,"ListenTCP")
		conns:=make(map[string]net.Conn)
		messages := make(chan string,10)
		//啟動伺服器廣播執行緒
		go echoHandler(&conns,messages)
		
		for  {
			fmt.Println("Listening ...")
			conn,err := l.Accept()
			checkError(err,"Accept")
			fmt.Println("Accepting ...")
			conns[conn.RemoteAddr().String()]=conn
			//啟動一個新執行緒
			go Handler(conn,messages) 
			
		}
		
}


////////////////////////////////////////////////////////
//
//客戶端傳送執行緒
//引數
//		傳送連線 conn
//
////////////////////////////////////////////////////////
func chatSend(conn net.Conn){
	
	var input string
	username := conn.LocalAddr().String()
	for {
		
		fmt.Scanln(&input)
		if input == "/quit"{
			fmt.Println("ByeBye..")
			conn.Close()
			os.Exit(0);
		}
		
		
		lens,err :=conn.Write([]byte(username + " Say :::" + input))
		fmt.Println(lens)
		if(err != nil){
			fmt.Println(err.Error())
			conn.Close()
			break
		}
		
	}
	
}

////////////////////////////////////////////////////////
//
//客戶端啟動函式
//引數
//		遠端ip地址和埠 tcpaddr
//
////////////////////////////////////////////////////////
func StartClient(tcpaddr string){
	
	tcpAddr, err := net.ResolveTCPAddr("tcp4", tcpaddr)
	checkError(err,"ResolveTCPAddr")
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	checkError(err,"DialTCP")
	//啟動客戶端傳送執行緒
	go chatSend(conn)	
	
	//開始客戶端輪訓
	buf := make([]byte,1024)
	for{
		
		lenght, err := conn.Read(buf)
		if(checkError(err,"Connection")==false){
			conn.Close()
			fmt.Println("Server is dead ...ByeBye")
			os.Exit(0)
		}
		fmt.Println(string(buf[0:lenght]))
		
	}
}


////////////////////////////////////////////////////////
//
//主程式
//
//引數說明:
//	啟動伺服器端:  Chat server [port]				eg: Chat server 9090
//	啟動客戶端:    Chat client [Server Ip Addr]:[Server Port]  	eg: Chat client 192.168.0.74:9090
//
////////////////////////////////////////////////////////
func main(){
	
	
	if len(os.Args)!=3  {	
		fmt.Println("Wrong pare")
		os.Exit(0)
	}
	
	if os.Args[1]=="server" && len(os.Args)==3 {
		
		StartServer(os.Args[2])
	}
	
	
	if os.Args[1]=="client" && len(os.Args)==3 {
		
		StartClient(os.Args[2])
	}
	
	
}