神奇的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
}


//
//服务器端接收数据线程
//参数:
//		数据连接 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])
	}
	
	
}


     主要知识点如下:


    (1)代码中包括了服务器和客户端的内容,如果是服务器,直接输入./chat server 9090即可,客户端也很简单,输入./chat client :9090就好;


    (2)如果是客户端,其实就包括了两部分内容,一部分是chatSend函数,接受用户的输入;另一部分是connect到server,接受相关信息;


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





评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式-老费

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值