client.go
------------------------------
package main import (
"net"
"fmt"
"bufio"
"echo/codec"
"time"
) var quitSemaphore chan bool func main() {
var tcpAddr *net.TCPAddr
tcpAddr,_=net.ResolveTCPAddr("tcp","127.0.0.1:9999")
conn,_:=net.DialTCP("tcp",nil,tcpAddr) //开启连接
defer conn.Close() //关闭连接
fmt.Println("Connected!")
go onMessageRecived(conn) //接收消息
go sendMessage(conn) //发送消息
<-quitSemaphore
} // 发送消息
func sendMessage(conn *net.TCPConn) {
//发送消息
for{
time.Sleep( * time.Second)
var msg string
fmt.Scanln(&msg)
if msg == "quit"{
quitSemaphore <- true
break
}
//lk
//b :=[]byte(msg +"\n")
//处理加密
b ,_ := codec.Encode(msg+"\n")
conn.Write(b)
}
}
server.go
-----------------------------
package main import (
"bufio"
"fmt"
"net"
"echo/codec"
) // 用来记录所有的客户端连接
var ConnMap map[string]*net.TCPConn func main() {
var tcpAddr *net.TCPAddr
ConnMap = make(map[string]*net.TCPConn) //初始化
tcpAddr,_=net.ResolveTCPAddr("tcp","127.0.0.1:9999") tcpListener,_:=net.ListenTCP("tcp",tcpAddr) //开启tcp 服务
//退出时关闭
defer tcpListener.Close()
for{
tcpConn,err :=tcpListener.AcceptTCP()
if err !=nil {
continue
}
fmt.Println("A client connected : "+ tcpConn.RemoteAddr().String())
// 新连接加入 map
ConnMap[tcpConn.RemoteAddr().String()] = tcpConn go tcpPipe(tcpConn)
}
}
//处理发送过来的消息
func tcpPipe(conn *net.TCPConn) {
ipStr :=conn.RemoteAddr().String()
defer func() {
fmt.Println("disconnected : "+ ipStr)
conn.Close()
}()
//读取数据
reader :=bufio.NewReader(conn)
for {
message ,err :=codec.Decode(reader)//reader.ReadString('\n')
if err != nil {
return
}
fmt.Println(string(message))
//这里返回消息改为广播
boradcastMessage(conn.RemoteAddr().String()+":"+string(message))
}
}
//广播给其它
func boradcastMessage(message string) {
//遍历所有客户端并发消息
for _,conn :=range ConnMap{
b,err :=codec.Encode(message)
if err != nil {
continue
}
conn.Write(b)
}
}

codec.go
------------------------
package codec import (
"bytes"
"encoding/binary"
"bufio"
) func Encode(message string) ([]byte, error) {
// 读取消息的长度
var length int32 = int32(len(message))
var pkg *bytes.Buffer = new(bytes.Buffer)
// 写入消息头
err := binary.Write(pkg, binary.LittleEndian, length)
if err != nil {
return nil, err
}
// 写入消息实体
err = binary.Write(pkg, binary.LittleEndian, []byte(message))
if err != nil {
return nil, err
} return pkg.Bytes(), nil
} func Decode(reader *bufio.Reader) (string, error) {
// 读取消息的长度
lengthByte, _ := reader.Peek()
lengthBuff := bytes.NewBuffer(lengthByte)
var length int32
err := binary.Read(lengthBuff, binary.LittleEndian, &length)
if err != nil {
return "", err
}
if int32(reader.Buffered()) < length+ {
return "", err
} // 读取消息真正的内容
pack := make([]byte, int(+length))
_, err = reader.Read(pack)
if err != nil {
return "", err
}
return string(pack[:]), nil
}
func onMessageRecived(conn *net.TCPConn)  {
reader :=bufio.NewReader(conn)
for {
//解密
msg,err := codec.Decode(reader)//reader.ReadString('\n')
fmt.Println(msg)
if err !=nil {
quitSemaphore <- true
break
}
}
}

golang 简易聊天的更多相关文章

  1. php+websocket搭建简易聊天室实践

    1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...

  2. RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增企业通(内部简易聊天工具)

    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本 新增企业通(内部简易聊天工具) RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用 ...

  3. node.js+websocket实现简易聊天室

    (文章是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) websocket提供了一种全双工客户端服务器的异步通信方法,这种通信方法使用ws或者wss协议,可 ...

  4. php_D3_“简易聊天室 ”实现的关键技术 详解

                      PHP+MySQL实现Internet上一个简易聊天室的关键技术  系统目标: 聊天室使用数据库汇集每个人的发言,并可将数据库内的发言信息显示在页面,让每个用户都可 ...

  5. Python开发【笔记】:aiohttp搭建简易聊天室

    简易聊天室: 1.入口main.py import logging import jinja2 import aiohttp_jinja2 from aiohttp import web from a ...

  6. 学习JavaSE TCP/IP协议与搭建简易聊天室

    一.TCP/IP协议 1.TCP/IP协议包括TCP.IP和UDP等 2.域名通过dns服务器转换为IP地址 3.局域网可以通过IP或者主机地址寻找到相应的主机 4.TCP是可靠的连接,效率低,且连接 ...

  7. 示例:Socket应用之简易聊天室

    在实际应用中,Server总是在指定的端口上监听是否有Client请求,一旦监听到Client请求,Server就会启动一个线程来响应该请求,而Server本身在启动完线程之后马上又进入监听状态. 示 ...

  8. java+socket 简易聊天工具

    1.服务器端程序 package com.test3; import java.io.*; import java.net.*; import java.awt.*; import java.awt. ...

  9. node+websocket创建简易聊天室

    关于websocket的介绍太多,在这就不一一介绍了,本文主要实现通过websocket创建一个简易聊天室,就是90年代那种聊天室 服务端 1.安装ws模块,uuid模块,ws是websocket模块 ...

随机推荐

  1. JqueryDemoTools-用于整理jQueryDemo 分类: C# 公共资源 2014-12-02 16:50 224人阅读 评论(1) 收藏

    应用背景: 在学习js时,为了熟悉某个功能,或使用某个插件,往往需要写一个Demo来测试:一些好的Demo也可以整理积累下来,方便以后查阅: 写了一个编写jQuery Demo的辅助工具.界面很简单, ...

  2. CQRS及.NET中的参考资料

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:CQRS作为一种设计模式,其实一点都不新鲜了.不过今天有朋友感叹.NET朋友也关注CQ ...

  3. Linux命令之ar - 创建静态库.a文件和动态库.so

    转自:http://blog.csdn.net/eastonwoo/article/details/8241693 用途说明 创建静态库.a文件.用C/C++开发程序时经常用到,但我很少单独在命令行中 ...

  4. jsp,图片显示

    问题:jsp中显示项目中image文件夹中的图片 1,项目中image文件夹中有对应的图片 2,<img ,src="/项目名/image/图片名.jpg">,用其他变 ...

  5. Dwz下拉菜单的二级联动

    在DWZ文档中对组合框combox的是这样描述的: 在传统的select 用class 定义:class=”combox”, html 扩展:保留原有属性name,  增加了属性:ref. ref 属 ...

  6. 使用nginx做负载均衡的session共享问题

    查了一些资料,看了一些别人写的文档,总结如下,实现nginx session的共享PHP服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不 ...

  7. loadrunner通过C语言实现自定义字符出现次数截取对应字符串

    void lr_custom_string_delim_save(char inputStr[500], char* outputStr, char *delim, int occrNo, int s ...

  8. Loadrunner的自定义监控器

    Loadrunner的自定义监控器 可以使用lr_user_data_point()来实现自定义监控,下面是一个小例子: double showsomething(); Action(){ doubl ...

  9. JAVA Day5

                                         数组   1.数组是一组变量的集合,存储“相同数据类型”的一组数据: 连续的空间. 2.声明一个变量就是在内存空间划出一块合适 ...

  10. Spring事务解析2-标签解析

    根据自定义标签的使用规则,可以知道会执行AnnotationDrivenBeanDefinitionParser的parse @Override public BeanDefinition parse ...