zoukankan      html  css  js  c++  java
  • 奇妙的go语言(聊天室的开发)


    【 声明:版权全部,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


        这是一篇关于聊天室开发的博客,原来文章的地址来自于。这篇文章非常具有代表性,对于代码中的函数部分内容,不想多说什么,仅仅是对它的实现进行一些必要的解说。关于代码,大家既能够在这里阅读,也能够跳转到那篇博客,继续阅读。


    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
    }
    
    ////////////////////////////////////////////////////////
    //
    //server端接收数据线程
    //參数:
    //		数据连接 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
    			
    	}
    		
    }
    
    ////////////////////////////////////////////////////////
    //
    //server发送数据的线程
    //
    //參数
    //		连接字典 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)
    			}
    			
    		}
    	}
    	
    }
    
    
    ////////////////////////////////////////////////////////
    //
    //启动server
    //參数
    //	端口 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)
    		
    		//启动server广播线程
    		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) 
    			
    		}
    		
    }
    
    
    ////////////////////////////////////////////////////////
    //
    //client发送线程
    //參数
    //		发送连接 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
    		}
    		
    	}
    	
    }
    
    ////////////////////////////////////////////////////////
    //
    //client启动函数
    //參数
    //		远程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")
    	//启动client发送线程
    	go chatSend(conn)	
    	
    	//開始client轮训
    	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]))
    		
    	}
    }
    
    
    ////////////////////////////////////////////////////////
    //
    //主程序
    //
    //參数说明:
    //	启动server端:  Chat server [port]				eg: Chat server 9090
    //	启动client:    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])
    	}
    	
    	
    }
    


         主要知识点例如以下:


        (1)代码中包含了server和client的内容,假设是server,直接输入./chat server 9090就可以,client也非常easy,输入./chat client :9090就好;


        (2)假设是client,事实上就包含了两部分内容,一部分是chatSend函数,接受用户的输入;还有一部分是connect到server,接受相关信息;


        (3)假设是server,略微复杂一点,有三个部分组成。第一部分就是不停地accept各个client;第二个就是为每个client创立Handler函数,接受client发来的信息;第三个就是echoHandler函数,它的作用就是将从某一用户接受过来的信息广播给其它全部的client,就是这么简单。





  • 相关阅读:
    SAS学习笔记27 卡方检验
    SAS学习笔记26 方差分析
    SAS学习笔记25 t检验(单个样本t检验、配对样本t检验、两个独立样本t检验及方差不齐时的t'检验)
    SAS学习笔记23 线性回归、多元回归
    HTML canvas画布
    HTML 新全局特性
    MYSQL数据库学习(五)如何自定义函数
    什么是单机结构?什么是集群?什么是分布式?
    MYSQL数据库学习(四)如何备份还原数据库
    MYSQL数据库学习(三)关于DML操作
  • 原文地址:https://www.cnblogs.com/yxwkf/p/3901384.html
Copyright © 2011-2022 走看看