goland 简单聊天室服务端

package main

import (
	"fmt"
	"net"
	"strings"
	"time"
)

type Client struct {
	C       chan string //用于发送数据的管道
	Name    string      //用户名
	Address string      //IP地址
}

//保存在线用户
var onLineMap map[string]Client

var message = make(chan string)

func Manager() {
	onLineMap = make(map[string]Client)
	for {
		msg := <-message //阻塞等待消息
		for _, cli := range onLineMap {
			cli.C <- msg
		}
	}
}

//发送消息给客户端
func WriteMessageToClient(cli Client, conn net.Conn) {
	for msg := range cli.C {
		//发送消息
		conn.Write([]byte(msg + "\n"))
	}
}
func MakeMsg(cli Client, msg string) (buf string) {
	buf = "[" + cli.Address + "]" + cli.Name + ":" + msg
	return
}

//处理用户连接
func HandleConn(conn net.Conn) {
	defer conn.Close()
	//获取连接客户端网络地址
	cliAddr := conn.RemoteAddr().String()
	//创建用户结构体
	cli := Client{make(chan string), cliAddr, cliAddr}
	onLineMap[cliAddr] = cli

	//新建协程,发送消息给客户端
	go WriteMessageToClient(cli, conn)
	//广播某人在线
	message <- MakeMsg(cli, "login")
	cli.C <- MakeMsg(cli, "i am here")

	isQuit := make(chan bool)  //用户是否主动退出
	hasData := make(chan bool) //用户是否发送过数据
	//新建协程接收用户发送信息
	go func() {
		buf := make([]byte, 2048)
		for {
			n, err := conn.Read(buf)
			if n == 0 { //用户退出
				isQuit <- true
				fmt.Println("conn.Read err=", err)
				return
			}
			msg := string(buf[:n-1])
			if len(msg) == 3 && msg == "who" {
				//发送用户列表
				conn.Write([]byte("user list:\n"))
				for _, data := range onLineMap {
					msg = data.Address + ":" + data.Name + "\n"
					conn.Write([]byte(msg))
				}
			} else if len(msg) >= 8 && msg[:6] == "rename" {
				//修改用户名
				cli.Name = strings.Split(msg, "|")[1]
				onLineMap[cli.Address] = cli
				conn.Write([]byte("rename success\n"))
			} else {
				//转发消息
				message <- MakeMsg(cli, msg)
			}
			hasData <- true
		}
	}()

	for {
		select {
		case <-isQuit:
			delete(onLineMap, cli.Address) //用户退出登录,移除用户
			message <- MakeMsg(cli, "login out")
			return
		case <-hasData:
		case <-time.After(60 * time.Second): //用户60秒不操作自动超时
			delete(onLineMap, cli.Address) //用户退出登录,移除用户
			message <- MakeMsg(cli, "time out leave out")
			return
		}
	}
}
func main() {
	//监听
	listener, err := net.Listen("tcp", ":8000")
	if err != nil {
		fmt.Println("net.Listen err=", err)
		return
	}
	defer listener.Close()

	//新建一个协程,转发消息
	go Manager()

	//主协程
	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("listener.Accept err=", err)
			continue
		}
		go HandleConn(conn) //处理用户连接
	}
}

  

原文地址:https://www.cnblogs.com/lemonzwt/p/10217190.html

时间: 2024-11-08 22:35:13

goland 简单聊天室服务端的相关文章

聊天室服务端的实现

该服务端是一个客户端连接进来新建一个线程,性能有待优化. socket服务端 public class MyServer { private int port; private ServerHandler serverHandler; public MyServer(int port,ServerHandler serverHandler) throws IOException{ System.out.println("初始化服务....."); this.setPort(port);

Python Socket 简单聊天室2

上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # -*- coding:utf-8 -*- import SocketServer class  mysocketclass(SocketServer.BaseRequestHandler):     def handle(self):         client_inform

ASP.NET 使用application和session对象写的简单聊天室程序

ASP.Net中有两个重要的对象,一个是application对象,一个是session对象. Application:记录应用程序参数的对象,该对象用于共享应用程序级信息. Session:记录浏览器端的变量对象,用来存储跨网页程序程序的变量或者对象. 说实话,写了快一年的asp.net,application对象还真没怎么用过.看了看书,根据这两个对象的特性写了一个简单的聊天室程序.真的是非常的简陋. 我的思路是,有两个页面Default页和ChatRoom页,页面布局如图: Default

C#实例之简单聊天室(状态管理)

前言        状态管理是在同一页或不同页的多个请求发生时,维护状态和页信息的过程.因为Web应用程序的通信协议使用了无状态的HTTP协议,所以当客户端请求页面时,ASP.NET服务器端都会重新生成一个网页实例.此时,旧网页的任务完成,旧网页的实例也随之消失.这种无状态,意味着客户端用户在浏览器中的一些状态或是对数据的一些修改都将丢失. 为了弥补这种基于web应用程序的固有限制,ASP.NET提供了多种用于管理状态的功能. 简单聊天室 这里运用System.Web命名空间的那些管理状态的类,

基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室.

Asp.Net SignalR - 简单聊天室实现

原文:Asp.Net SignalR - 简单聊天室实现 简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 持久链接类有一个Groups的对象,通过这个对象,我们可以进行分组添加人员.发送消息.删除人员等操作 在连接事件中,给当前游客指定随机名称,并且返回当前已有的聊天室信息 protected override Task OnConnected

Java简单聊天室

实现Java简单的聊天室 所用主要知识:多线程+网络编程 效果如下图 /** * * @author Administrator * * 简单的多人聊天系统——重点:同时性,异步性 * 1.客户端:发送消息,并且接收消息 * 1.1 消息发送至服务器:服务器每次都将客户发过来的信息发送到每个客户端 * 1.2 接收消息:发送的同时也要接收消息,所以必须有两个线程,一个发送消息,一个接收消息 * 1.3 关于这两个线程:如果没有线程,接收和发送就是按顺序执行的了,那么是发送后接收还是接收后发送?或

用swoole和websocket开发简单聊天室

首先,我想说下写代码的一些习惯,第一,任何可配置的参数或变量都要写到一个config文件中.第二,代码中一定要有日志记录和完善的报错并记录报错.言归正传,swoole应该是每个phper必须要了解的,它号称重新定义了php.此聊天室利用了swoole高并发并且异步非阻塞的特点提高了程序的性能. 首先,定义一个 swoole_lock 和 swoole_websocket_server ,并且配置参数,具体参数详情可以去swoole官网查看. public function start(){ $t

使用socket实现简单聊天室

通过socket实现简单的聊天室 1.服务端代码:serverselect.py #!/usr/bin/env python #coding:utf8 import socket import select class SelectServer(object): def __init__(self,host,port,backlog): self.host = host self.prot = port self.address = (host,port) self.backlog = back