首页 > 其他分享 >使用Go实现一个百行聊天服务器

使用Go实现一个百行聊天服务器

时间:2023-12-16 22:23:32浏览次数:31  
标签:err client Client 百行 Go 服务器 server conn 客户端

前段时间, redis作者不是整了个c语言版本的聊天服务器嘛, 地址, 代码量拢共不过百行.

于是, 心血来潮下, 我也整了个Go语言版本. 简单来说就是实现了一个聊天室的功能. 将所有注释空行都去掉, 刚好100行实现. 废话不多说, 先上代码:

package main

import (
	"fmt"
	"log"
	"net"
	"strings"
	"sync"
)

type Server struct { // 服务端内容
	clients map[string]*Client
	lock    sync.Mutex
}

func (s *Server) delClient(client *Client) { // 客户端关闭
	s.lock.Lock()
	defer s.lock.Unlock()
	delete(s.clients, client.name)
}

func (s *Server) addClient(client *Client) { // 客户端关闭
	s.lock.Lock()
	defer s.lock.Unlock()
	s.clients[client.name] = client
}

func (s *Server) sendMsgToOtherClient(msg string, client *Client) { // 将消息发送给其他所有客户端
	s.lock.Lock()
	defer s.lock.Unlock()
	// 将消息转发给其他客户端
	for _, c := range s.clients {
		if c != client {
			c.msgCh <- "msg-> " + client.name + ": " + msg + "\n"
		}
	}
}

type Client struct { // 定义客户端
	conn   net.Conn
	name   string      // 当前客户端的名称
	msgCh  chan string // 发送消息的管道
	server *Server
}

func (c *Client) receive() { // 接收消息
	for msg := range c.msgCh {
		_, _ = c.conn.Write([]byte(msg))
	}
}

func (c *Client) close() {
	c.server.delClient(c)
	close(c.msgCh)
	_ = c.conn.Close()
}

func (c *Client) handle() { // 开始处理连接
	_, _ = c.conn.Write([]byte(fmt.Sprintf("hello %s!\n", c.name))) // 发送欢迎信息
	c.server.sendMsgToOtherClient("join", c)                        // 通知大家, 有人加入了聊天室
	defer c.close()
	for {
		buf := make([]byte, 2048)
		n, err := c.conn.Read(buf) // 接收客户端发送的消息
		if err != nil {
			log.Printf("receive client data error: %s", err.Error())
			return
		}

		msg := strings.TrimSpace(string(buf[:n]))
		if len(msg) == 0 {
			continue
		}
		if msg == "quit" {
			c.server.sendMsgToOtherClient("quit", c) // 通知大家, 有人退出了聊天室
			return
		}
		c.server.sendMsgToOtherClient(msg, c)
	}
}

func main() {
	// 监听端口
	listener, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	server := &Server{
		clients: make(map[string]*Client),
		lock:    sync.Mutex{},
	}

	nameIndex := 1
	for {
		conn, err := listener.Accept() // 建立连接
		if err != nil {
			log.Println(err)
			continue
		}

		client := &Client{
			conn:   conn,
			msgCh:  make(chan string, 100),
			name:   fmt.Sprintf("user%d", nameIndex),
			server: server,
		}
		nameIndex++
		server.addClient(client)
		go client.handle()
		go client.receive()
		log.Printf("new client: %s\n", conn.RemoteAddr())
	}
}

可以直接telnet作为客户端连接, 实现的功能简单来说就是一个大的聊天室, 用户发的消息会同步发给所有用户. (因代码篇幅和复杂度原因, 就不对代码做详细说明了)

看下聊天室效果:

image-20231216220013277

当然了, 还是有很多极限情况没有处理, 很多异常情况没有判断. 比如:

  • 客户端数量没有控制
  • 缺少客户端心跳
  • 缺少错误处理
  • 缺少安全性检查
  • 客户端发送消息的长度限制
  • 等等...

但总得来说, 作为一个玩具还是可以的, 而且也达到百行的要求咯.(这也是我改了几版才改到百行的..)

标签:err,client,Client,百行,Go,服务器,server,conn,客户端
From: https://www.cnblogs.com/hujingnb/p/17908482.html

相关文章

  • 第八章:SpringBoot-Java工程及关系和修改启动logo(了解)
    一、springbootJava工程(了解)二、关闭&修改启动logo(了解)......
  • 数据结构与算法 第一章(48课时课程笔记)Data Structure and Algorithms
    数据结构基础知识 数据(Data):是对信息的一种符号表示。在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。数据元素(DataElement):是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。一个数据元素可由若干个数据项(DataItem)组成。数据......
  • 2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和
    2023-12-16:用go语言,给定整数数组arr,求删除任一元素后,新数组中长度为k的子数组累加和的最大值。来自字节。答案2023-12-16:来自左程云。灵捷3.5大体步骤如下:算法maxSum1分析:1.计算输入数组arr的长度n。2.如果n<=k,则返回0。3.初始化ans为int类型的最小值(math......
  • 2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和
    2023-12-16:用go语言,给定整数数组arr,求删除任一元素后,新数组中长度为k的子数组累加和的最大值。来自字节。答案2023-12-16:来自左程云。灵捷3.5大体步骤如下:算法maxSum1分析:1.计算输入数组arr的长度n。2.如果n<=k,则返回0。3.初始化ans为int类型的最小值(math.MinInt32)......
  • MongoDB中的分布式集群架构
    MongoDB中的分布式集群架构前言ReplicaSet副本集模式副本集写和读的特性Sharding分片模式分片的优势MongoDB分片的组件分片键chunk是什么分片的算法哈希分片范围分片总结参考MongoDB中的分布式集群架构前言前面我们了解了MongoDB中的索引,......
  • 服务器raid5两块硬盘离线数据恢复
    IBMV5000的故障如下:一块硬盘红灯闪亮,机器还在正常运行,但没有多久,系统就不能正常运行,这时才发现另一块硬盘的红灯也在闪亮。 磁盘阵列数据恢复过程:1.启动服务器,自检至阵列时按Ctrl+M进入NetRaid管理程序。查看阵列信息,发现硬盘下线,运用修改配置将一硬盘强行设置成上线。重新启......
  • ubuntu22.04安装Goland2022.2.4
    ubuntu22.04安装Goland2022.2.4自行下载Goland版本下载golandwgethttps://download.jetbrains.com/go/goland-2022.2.4.tar.gz./将下载的压缩文件解压到指定目录sudotar-zxvfgoland-2022.2.4.tar.gz-C/tools/goland启动试运行golandcd/tools/goland/GoLand......
  • 阿贝云免费云服务器个人评价
    阿贝云是一家提供免费云服务器的云服务提供商,下面是对其性能的评价。首先,阿贝云的免费云服务器性能表现良好。它提供了稳定可靠的服务器运行环境,可以满足简单的网站部署、数据存储和应用开发等基本需求。免费云服务器配置合理,RAM和CPU资源分配足够,可以支持一般的应用程序运行。......
  • 服务器系统安装
    制作支持UEFI引导的U盘在Systemx服务器上安装WindowsServer2008R2操作系统本例是在Systemx3550M55463型上通过U盘安装WindowsServer2008R2操作系统,其他机型以U盘方式安装系统或者以刻录DVD光盘方式安装系统,也可参考本例。 若服务器全新或者所有阵列及数据皆可删除,也......
  • golang封装命令做pipe管道
    packagemainimport( "fmt" "io" "os/exec")funcmain(){ fmt.Println("vim-go") //pipeReader,pipeWriter:=io.Pipe() binPath:="../03-ncpk-nvm/nvm" binArgs:=[]string{ "-debug",......