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. windows64系统中mysql64位绿色安装

    将下载压缩包解压到任意目录 配置安装文件: # For advice on how to change settings please see# http://dev.mysql.com/doc/re ...

  2. 跟着鸟哥学Linux系列笔记3-第11章BASH学习

    跟着鸟哥学Linux系列笔记0-扫盲之概念 跟着鸟哥学Linux系列笔记0-如何解决问题 跟着鸟哥学Linux系列笔记1 跟着鸟哥学Linux系列笔记2-第10章VIM学习 认识与学习bash 1. ...

  3. 编辑login.sql进行sqlplus登陆设置

    执行SQLPLUS登录到SQL 界面时候,就会自动的加载 $ORACLE_HOME/sqlplus/admin 中的login.sql(若没有则加载glogin.sql) 这里面的东西 是根据自己的爱 ...

  4. 谈谈网站插入youtube视频播放

    最近需要在网页首页追加视频播放功能. 需要播放youtube视频.中间遇到一些波折.特来分享一下. 首先像网页添加视频文件我们通常够采用embed标签. 标签里可以设置很多的关键子.我们可以配置为fl ...

  5. 函数fseek() 用法(转)

    在阅读代码时,遇到了很早之前用过的fseek(),很久没有用了,有点陌生,写出来以便下次查阅. 函数功能是把文件指针指向文件的开头,需要包含头文件stdio.h fseek   函数名: fseek ...

  6. 允许webservice远程测试

    System.Web节点下添加 <webServices> <protocols> <add name= "HttpPost"/> <ad ...

  7. JS对Array进行自定制排序

    JS对Array进行自定制排序,简单的做一个记录,代码如下所示: //Test function function myFunction(){ var myArr = new Array(); var ...

  8. HTML概况性介绍

    HTML(HyperText Markup Language)汉语的意思是:超文本标记语言. ”超文本”是指.html页面内不仅仅可以包含文字,还可以包含图片.链接,甚至音乐.程序等非文字元素. “标 ...

  9. 关于Vector中的元素中含有指针成员的情况

    对于容器,当容器的各个元素为类类型,且该类类型中含有指针成员时: 如果类类型的析构函数中包含了对指针变量指向内存的释放操作,则在利用clear()函数删除容器所有元素时,会自动调用类的析构函数,自动实 ...

  10. APK瘦身实践

    首发地址:http://www.jayfeng.com/2015/12/29/APK%E7%98%A6%E8%BA%AB%E5%AE%9E%E8%B7%B5/ 因为推广的需要,公司需要把APK的大小再 ...