golang grpc chat demo

该博客介绍了一个使用gRPC和Proto3构建的双向流聊天应用。服务端和客户端通过配置文件设置认证信息,利用grpc的Header传递用户名和密码进行身份验证。客户端和服务器端分别使用Goroutines处理消息的接收和发送。服务端接收到消息后会广播给所有已认证的用户。源代码可在提供的GitHub链接中查看。
摘要由CSDN通过智能技术生成

运行方式

修改配置

[Server]
监听端口
port = 8888

[Auth]
# 用户名和密码对
mike = 123456
leo = password

运行服务端

./server 

客户端

./client -u leo -p password

效果

chat

设计

使用grpc双向流收发消息,proto文件如下

syntax = "proto3";
package chat_server;
option go_package="./chat_server";

service ChatServer {
    rpc Chat (stream ChatRequest) returns (stream ChatResponse) {}
}
message ChatRequest {
  string msg = 1;
}

message ChatResponse {
  string msg = 1;
  string user = 2;
}

grpc header中传递用户名和密码用来验证

conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
	log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := chat_server.NewChatServerClient(conn)
md := metadata.New(map[string]string{"user": user, "pwd": pwd})
stream, err := client.Chat(metadata.NewOutgoingContext(context.Background(), md))

客户端逻辑

// 创建Goroutine 接受服务端消息
	go func() {
		for {
			in, err := stream.Recv()
			//....
			response <- in
		}
	}()
// 创建Goroutine 接受用户输入发送到服务端
go func() {
	for {
		stream.Send(&chat_server.ChatRequest{Msg: <-request})
	}
}()
// 创建Goroutine 运行用户界面,接受消息到request channel
go func() {
	t, err := tcell.New()
	if err != nil {
		panic(err)
	}
	// ...
}

服务端逻辑

func (s *Server) Chat(stream chat_server.ChatServer_ChatServer) error {
	// 存放连接 map[用户名】连接
	s.mu.Lock()
	md, _ := metadata.FromIncomingContext(stream.Context())
	user, pwd := md.Get("user")[0], md.Get("pwd")[0]
	s.clients[user] = stream
	s.mu.Unlock()
	if v, ok := Users[user]; !(ok && v == pwd) {
		return fmt.Errorf("login failed")
	}
	log.Printf("user 【%s】login\n", user)
	for {
		in, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}

		log.Printf("received msg 【%s】from user 【%s】\n", in.Msg, user)
		// 收到消息,依次投递给每个用户
		for u, client := range s.clients {
			log.Printf("send msg from user 【%s】to user【%s】\n", user, u)
			err := client.Send(&chat_server.ChatResponse{Msg: in.Msg, User: user})
			if err != nil {
				log.Printf("send msg to user %s failed: %v", u, err)
				log.Printf("delete user %s session\n", u)
				s.mu.Lock()
				delete(s.clients, u)
				s.mu.Unlock()
			}
		}
	}
}

源代码

https://github.com/LeoBest2/grpc-chat-demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值