go 聊天室开发详解 channel chan 协程 并发执行

一、思路

定义好3个通道  entering,leaving,massages分别为登录,登出(单向输入通道)和信息(双向通道)。
开启两个协程,一个协程负责监听通道是否有输入或输出,一个协程负责组织发送的内容和流程的控制     演示地址(http://main.cladmining.top)

二、具体代码加详细说明

package Controller

import (
	"bufio"
	"fmt"
	"log"
	"net"
)
//聊天室
func MassagesStart(){
	listener, err := net.Listen("tcp", "localhost:8099")
	if err != nil {
		log.Fatal(err)
	}
	go broadcaster()  //这里需要先消费chan里面的值 会阻塞
	for {
		conn, err := listener.Accept() //等待并且返回下一个监听到的链接
		if err != nil {
			log.Print(err)
			continue
		}
		go handleConn(conn)  //往通道里面写值
	}
}

type client chan<- string

//定义三个通道
var (
	entering =make(chan client)  //登入的通道
	leaving =make(chan client)   //离开的通道
	massages=make(chan string)   //发送消息的童道
)

func broadcaster()  {
	clients:=make(map[client]bool)
	for {
		select {
		case msg:=<-massages: //有消息进来的时候循环去发送消息
			for cli:=range clients{
				cli<-msg
			}
		case cli:=<-leaving://关闭客户端的时候
			delete(clients,cli)
			close(cli)
		case cli:=<-entering:
			clients[cli]=true
		}
	}
}

func handleConn(conn net.Conn)  {
	ch:=make(chan string)   //定义一个字符串传输通道
	go clientWriter(conn,ch)   //起一个协程顺着通道往链接里面发字符串
	who:=conn.RemoteAddr().String()  //把地址转成字符串
	ch<-"you are a pig,your address is:"+who
	massages<- who+":are login"
	entering<-ch
	input:=bufio.NewScanner(conn)
	for input.Scan() { //逐行扫描
		massages<-who+":"+input.Text()
	}
	leaving<-ch  //chan 存入或取出的时候会阻塞ch里面有值  当你关闭链接的时候 leaving读取到的是一个空字符串 然后程序往下执行
	massages<-who+":has leaving"
	conn.Close()
}

func clientWriter(conn net.Conn,ch chan string)  {
	for msg:=range ch{
		fmt.Fprintln(conn,msg)  //与fmt.println相比较多了一个往conn写的操作
	}
}

三、注意事项

通道的阻塞,select的应用tcp连接间的通信。展示图片
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值