奇妙的go语言(聊天室的开发)

奇妙的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,就是这么简单。





版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118722.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CAN通信(一)——认识CAN总线[通俗易懂]

    CAN总线通俗易懂CAN总线背景CAN总线是什么网络拓扑节点、报文、信号CAN总线背景作为并非通信专业的土鳖汽车工程师,CAN通信是必须掌握的,但是,记得刚开始上来一看什么定义(什么串行数据通信协议,什么物理层和数据链路层功能,什么帧处理,位填充。。。刚学的时候确实一脸懵)。所以,我只从汽车工程师的角度讲讲我能理解和用得到的CAN通信,才疏学浅,请各位指教!关于OSI模型、物理层、数据链路层,高低电平、数据帧。。等等等,请自行查看如下链接:链接:https://blog.csdn.net/kgc

    2022年4月11日
    68
  • 利用139邮箱的免费短信提醒作为报警接口「建议收藏」

    利用139邮箱的免费短信提醒作为报警接口「建议收藏」各位开发者手机短信里肯定都收到过线上业务报警短信,邮箱里肯定有更多报警邮件,很多公司都把报警信息通过邮件发送,但是这样不能保证接收到。通过短信发送的话,即使很多短信接口很便宜,但是每条也有四五分钱,而且报警信息通过不会单个出现,所以,万一bug集中出现,就亏大了。然后我发现了个神器,以前一直没有注意的垃圾信息:移动提供的默认139邮箱,每次收到邮件都会发送免费短信,既然这样,为何不把报警邮件发到13

    2022年10月13日
    3
  • java sql拼接字符串_SQL中字符串拼接

    java sql拼接字符串_SQL中字符串拼接1.概述在SQL语句中经常需要进行字符串拼接,以sqlserver,oracle,mysql三种数据库为例,因为这三种数据库具有代表性。sqlserver:select’123’+’456′;oracle:select’123’||’456’fromdual;或selectconcat(‘123′,’456’)fromdual;mysql:selectconcat(‘123’,’…

    2022年6月16日
    102
  • xmind打不开xmind文件_鼠标双击无法打开文件

    xmind打不开xmind文件_鼠标双击无法打开文件声明:请大家支持正版!此文仅作个人交流学习!很多小伙伴安装完Xmind后会发现双击无法打开文件,只能在应用界面打开,我在网上也看了很多解决方案,但是很多都是没用的,比如这个:还有说把最大支持的文件大小改成128m,亲测没用。还有想着把pojie包配置给注释掉的,这种可能也是为了支持正版吧/手动狗头后来试了很多方法,发现更改一下pojie包的路径就好了,改成绝对路径就可以直接打开。我用的是xmind8update9版本,亲测可行,如果其他版本的小伙伴试了不行的话,可以评论区一起交流一下~..

    2025年8月8日
    4
  • 贾尚文_roc指标详解及实战用法

    贾尚文_roc指标详解及实战用法文章目录混淆矩阵ROCAOUPRCF1-Score多分类的F1-Score选择指标ROC曲线和AUC常被用来评价一个二值分类器的优劣。混淆矩阵其中,TP(真正,TruePositive)表示真正结果为正例,预测结果也是正例;FP(假正,FalsePositive)表示真实结果为负例,预测结果却是正例;TN(真负,TrueNegative)表示真实结果为正例,预测结果却是负例…

    2022年8月31日
    4
  • 生命游戏(两),有一种东西叫CCScrollView

    生命游戏(两),有一种东西叫CCScrollView

    2022年1月2日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号