关键词:
package tools
import (
"bufio"
"os"
"strings"
)
func SanLine() string
inputReader := bufio.NewReader(os.Stdin)
input,_ := inputReader.ReadString('\n')
return strings.Replace(input, "\n", "", -1)
package main
import (
"os"
"fmt"
"net"
"log"
"strings"
"goLearn/chatroom/ircTest/tools"
)
func main()
// conns[string]net.Conn用于保存昵称和conn对应关系的map
conns := make(map[string]net.Conn)
//传递消息的channel
msgCh := make(chan string, 10)
if len(os.Args) != 2
fmt.Println("PLease input: \" cmd [:port] \"")
os.Exit(0)
port := os.Args[1]
addr, err := net.ResolveTCPAddr("tcp", port)
if err != nil
log.Fatal(err)
// 开始监听
listener, err := net.ListenTCP("tcp", addr)
log.Println("服务器启动")
// 启动广播协程
go broadcast(msgCh, &conns)
// 启动serverTools()协程
go serverTools(msgCh, &conns)
for
conn, err := listener.Accept()
if err != nil
log.Fatal(err) //todo:这里可能有问题
go ServerHandle(conn, msgCh, &conns)
func ServerHandle(conn net.Conn, msgCh chan string, conns *map[string]net.Conn)
//发送欢迎信息
conn.Write([]byte("您已连接"))
var msg string
data := make([]byte, 1024)
for
length, err := conn.Read(data)
// 如果读取错误,可以认为是客户端退出或者关闭了连接,
// 那么就关闭与客户端的连接,break出for-loop,相当于退出了这个conn的handle()函数
if err != nil
// 这里有问题,如果客户端没有quit,而是直接退出,那么这个昵称及conn的键值对还在conns里,
// 下次连接时,服务器查询conns,会认为这个昵称已存在
conn.Close()
break
// 如果读到消息,那么将消息有效部分之后的一位置为0
// todo: 暂时不知道为什么这么做
if length > 0
data[length] = 0
// 客户端发来的消息是带"前缀"的,解析消息,将"前缀"和消息体分开
cmd := strings.Split(string(data[:length]), "|")
// 打印带有前缀的消息有效部分
fmt.Println(string(data[:length]))
// 开始判断消息前缀,做相应的处理
switch cmd[0]
// 前缀"hello"代表客户端请求一个昵称
case "hello":
// 昵称在conns中已经存在,代表重名,退出客户端连接
// todo:这里怎么样可以改成不断开,而是让客户端重新尝试起名字
if _, ok := (*conns)[cmd[1]]; ok
conn.Close()
else
// 将昵称和conn的键值对存入map,昵称作为key
(*conns)[cmd[1]] = conn
msg = fmt.Sprintf("[%s] join...", cmd[1])
case "say":
msg = fmt.Sprintf("[%s] : %s", cmd[1], cmd[2])
case "quit":
msg = fmt.Sprintf("quit|[%s]", cmd[1])
// 将匹配模式生成的消息传给channel
msgCh <- msg
func broadcast(msgCh chan string, conns *map[string]net.Conn)
for
msg := <-msgCh
// 遍历所有客户端,向客户端发送消息
for name, conn := range *conns
_, err := conn.Write([]byte(msg))
// 如果向某一个客户端发送消息失败,那么我们认为该客户端已经退出或者关闭了连接,
// 那么就需要将该客户端在conns中保存的键值对删掉
if err != nil
delete(*conns, name)
// serverTools() 用来定义server端的一些行为和工具,例如server的发言,server踢人等。
func serverTools(msgCh chan string, conns *map[string]net.Conn)
msg := tools.SanLine()
// cmd是一个[]string
cmd := strings.Split(string(msg), "|")
log.Println(cmd)
if len(cmd) > 1
switch cmd[0]
case "kick":
if _, ok := (*conns)[cmd[1]]; ok
(*conns)[cmd[1]].Close()
msgCh <- "[Server]: Kick out [" + cmd[1] + "]"
default:
msgCh <- "[Server]" + string(msg)
else
msgCh <- "[Server]:" + string(msg)
package main
import (
"os"
"fmt"
"net"
"log"
"strings"
"goLearn/chatroom/ircTest/tools"
)
func main()
// conns[string]net.Conn用于保存昵称和conn对应关系的map
conns := make(map[string]*net.Conn)
//传递消息的channel
msgCh := make(chan string, 10)
if len(os.Args) != 2
fmt.Println("PLease input: \" cmd [:port] \"")
os.Exit(0)
port := os.Args[1]
addr, err := net.ResolveTCPAddr("tcp", port)
if err != nil
log.Fatal(err)
// 开始监听
listener, err := net.ListenTCP("tcp", addr)
log.Println("服务器启动")
// 启动广播协程
go broadcast(msgCh, conns)
// 启动serverTools()协程
go serverTools(msgCh, conns)
for
conn, err := listener.Accept()
if err != nil
log.Fatal(err)
go ServerHandle(&conn, msgCh, conns)
func ServerHandle(conn *net.Conn, msgCh chan string, conns map[string]*net.Conn)
//发送欢迎信息
(*conn).Write([]byte("您已连接"))
var msg string
data := make([]byte, 1024)
for
length, err := (*conn).Read(data)
// 如果读取错误,可以认为是客户端退出或者关闭了连接,
// 那么就关闭与客户端的连接,break出for-loop,相当于退出了这个conn的handle()函数
if err != nil
(*conn).Close()
// 如果客户端没有通过conn.Close()来断开连接,而是直接关闭程序或者网络中断,那么服务器端主动断开链接,
// 并且删除保存在conns中的项目,以避免下次客户端登陆时,出现因为同名而断开的情况。
for name, connItem := range conns
if conn == connItem
delete(conns, name)
break
// 客户端发来的消息是带"前缀"的,解析消息,将"前缀"和消息体分开
cmd := strings.Split(string(data[:length]), "|")
// 打印带有前缀的消息有效部分
fmt.Println(string(data[:length]))
// 开始判断消息前缀,做相应的处理
switch cmd[0]
// 前缀"hello"代表客户端请求一个昵称
case "hello":
// 昵称在conns中已经存在,代表重名,退出客户端连接
// todo:这里怎么样可以改成不断开,而是让客户端重新尝试起名字
if _, ok := conns[cmd[1]]; ok
(*conn).Write([]byte("重名啦!!!!!"))
(*conn).Close()
else
// 将昵称和conn的键值对存入map,昵称作为key
/*
指针的定以后如果没有指向任何变量,那么为nil(空指针)。*p = *q这种表达式,是把*p指向的内存地址报错
的数据更改为*q指向内存地址保存的数据,相当于复制了一份,内存地址还是不一样。操作的是数据。所以下面这
里表达式两遍的指针不能加*,下面代码的目的是为了把conn的内存地址保存在conns中,以便于后续代码操作的
是同一个conn。如果加了*(前提是conns[cmd[1]]已经被初始化过),那么相当于是把conn指向的值赋值给了
conns[1]指针指向的内存,两个指针指向的内存还是不一样。
*/
conns[cmd[1]] = conn
msg = fmt.Sprintf("[%s] join...", cmd[1])
case "say":
msg = fmt.Sprintf("[%s] : %s", cmd[1], cmd[2])
case "quit":
msg = fmt.Sprintf("quit|[%s]", cmd[1])
// 将匹配模式生成的消息传给channel
msgCh <- msg
func broadcast(msgCh chan string, conns map[string]*net.Conn)
for
msg := <-msgCh
// 遍历所有客户端,向客户端发送消息
for name, conn := range conns
_, err := (*conn).Write([]byte(msg))
// 如果向某一个客户端发送消息失败,那么我们认为该客户端已经退出或者关闭了连接,
// 那么就需要将该客户端在conns中保存的键值对删掉
if err != nil
delete(conns, name)
// serverTools() 用来定义server端的一些行为和工具,例如server的发言,server踢人等。
func serverTools(msgCh chan string, conns map[string]*net.Conn)
for
msg := tools.SanLine()
// cmd是一个[]string
cmd := strings.Split(string(msg), " ")
var kickOutInfo string
if len(cmd) > 1
switch cmd[0]
case "kick":
log.Println("check kick")
var conn *net.Conn
conn = conns[cmd[1]]
if _, ok := conns[cmd[1]]; ok
(*conn).Close()
delete(conns, cmd[1])
log.Println(conns)
//msgCh <- "[Server]: Kick out [" + cmd[1] + "]"
kickOutInfo = "[Server]: Kick out [" + cmd[1] + "]"
default:
if len(kickOutInfo) > 0
msgCh <- kickOutInfo
else
msgCh <- "[Server]" + string(msg)
else
msgCh <- "[Server_say]:" + string(msg)
package main
import (
"os"
"fmt"
"net"
"log"
"strings"
"goLearn/chatroom/ircTest/tools"
)
func main()
if len(os.Args) != 2
fmt.Println("PLease input: \" cmd [:port | IPaddress:port] \"")
os.Exit(0)
port := os.Args[1]
addr, err := net.ResolveTCPAddr("tcp", port)
if err != nil
log.Fatal(err)
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil
log.Fatal(err)
// 用于保存消息
msg := make([]byte, 1024)
// 读取欢迎消息
conn.Read(msg)
fmt.Println(string(msg))
// 输入昵称
fmt.Print("请输入昵称:")
nickname := tools.SanLine()
fmt.Println("Hello", nickname)
// 向服务器发送"hello|nickname",尝试定义昵称,如果昵称重名,这里会直接退出,尝试修改为可以不断尝试
conn.Write([]byte("hello|" + nickname))
// 开启接收数据的协程
go ClientHandle(conn, nickname)
// 发送消息
// 考虑一下放在一个单独的函数中怎么实现
for
msg := tools.SanLine()
if msg == "quit"
conn.Write([]byte("quit|" + nickname))
// 如果发送quit,客户端主动关闭conn
conn.Close()
conn.Write([]byte("say|" + nickname + "|" + msg))
func ClientHandle(conn *net.TCPConn, nickname string)
for
msg := make([]byte, 1024)
_, err := (*conn).Read(msg)
if err != nil
// 如果这里从服务器端conn读取失败,可以认为是服务器关闭连接或者退出了
log.Fatal(err)
// 将自身的发言屏蔽
if strings.Contains(string(msg), "["+nickname+"] : ") == false
fmt.Println(string(msg))
package main
import (
"os"
"fmt"
"net"
"log"
"strings"
"goLearn/chatroom/ircTest/tools"
)
func main()
if len(os.Args) != 2
fmt.Println("PLease input: \" cmd [:port | IPaddress:port] \"")
os.Exit(0)
port := os.Args[1]
addr, err := net.ResolveTCPAddr("tcp", port)
if err != nil
log.Fatal(err)
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil
log.Fatal(err)
// 用于保存消息
msg := make([]byte, 1024)
// 读取欢迎消息
conn.Read(msg)
fmt.Println(string(msg))
// 输入昵称
fmt.Print("请输入昵称:")
nickname := tools.SanLine()
fmt.Println("Hello", nickname)
// 向服务器发送"hello|nickname",尝试定义昵称,如果昵称重名,这里会直接退出,尝试修改为可以不断尝试
conn.Write([]byte("hello|" + nickname))
// 开启接收数据的协程
go ClientHandle(conn, nickname)
// 发送消息
for
msg := tools.SanLine()
if msg == "quit"
conn.Write([]byte("quit|" + nickname))
// 如果发送quit,客户端主动关闭conn
conn.Close()
conn.Write([]byte("say|" + nickname + "|" + msg))
func ClientHandle(conn *net.TCPConn, nickname string)
for
msg := make([]byte, 1024)
_, err := (*conn).Read(msg)
if err != nil
// 如果这里从服务器端conn读取失败,可以认为是服务器关闭连接或者退出了
log.Fatal(err)
// 将自身的发言屏蔽
if strings.Contains(string(msg), "["+nickname+"] : ") == false
fmt.Println(string(msg))
golang:cobra包简介(代码片段)
Cobra是一个Golang包,它提供了简单的接口来创建命令行程序。同时,Cobra也是一个应用程序,用来生成应用框架,从而开发以Cobra为基础的应用。本文的演示环境为ubuntu18.04(下图来自互联网)。主要功能cobra的主要功能如下,可以说... 查看详情
irc(代码片段)
什么是IRCIRC(Internet Relay Chat的缩写,“因特网中继聊天”)是一种透过网络的即时聊天方式。其主要用于群体聊天,但同样也可以用于个人对个人的聊天。IRC使用的服务器端口有6667(明文传输,如irc://irc.freenode.net)、66... 查看详情
golang命令行库cobra的使用(代码片段)
简介Cobra既是一个用来创建强大的现代CLI命令行的golang库,也是一个生成程序应用和命令行文件的程序。下面是Cobra使用的一个演示:Cobra提供的功能简易的子命令行模式,如appserver,appfetch等等完全兼容posix命令行模式嵌套子命... 查看详情
Twitch IRC 聊天机器人成功连接但未检测到命令
...间】:2015-10-1001:41:17【问题描述】:我开始使用Python制作一个简单的Twitch聊天机器人。它连接良好,并且还可以看到其他人在聊天中发送的消息。然而,我的问题是我似乎无法在使用命令时检测到它们。我可以获取聊天条目的用... 查看详情
golang系列文章:打印命令行参数(代码片段)
记得最早在学校机房学习Java时,写一个最简单main方法,当程序运行并在屏幕上打印出helloworld时,内心还有些小激动呢,相信很多人都有这种经历吧。今天想借助命令行程序,总结一下Go语言的基础知识点。首先,来一个Go语言... 查看详情
golang简单的golang聊天服务器(代码片段)
查看详情
什么是后门病毒?
...,IRC全名为InternetRelayChat,是一款即时聊天工具,类似网络聊天室,但功能更强大。IRC客户端与服务端通信采用的端口和相应协议是公开的,现在网上有很多IRC客户端软件,各有特色。同时,也正是由于协议的公开,给了病毒可乘... 查看详情
连接到 Twitch IRC 聊天
...题描述】:您好,我已尝试,因此我可以尝试为twitch制作一个简单的聊天机器人,但我正在努力使其工作。我得到错误:http://puu.sh/j3HwK/173a0388fb.png这里是代码:<?phpset_time_limit(0);ini_set(\'display_errors\' 查看详情
irc关键操作(代码片段)
...)。此功能是服务器通过提供NickServ服务(其实语法上就是一个用户,类似的服务还有ChanServMemoServ)实现的。假定需要重置密码的用户名为foo,那首先可以查看 查看详情
简易命令行聊天室程序
...到的问题。0、该程序实现的基本功能编写了一个简单的聊天室程序,该聊天室程序能够让所有的用户同时在线群聊,它分为服务器和客户端两个部分。服务器:接收客户端数据,并将该客户端数据发送给其他登录到该服务器上... 查看详情
尝试irc&freenode
...下客户端,命令行版本的我试了一下weechat(和微信就差一个字母),图形的用了TimeChat。 并没有推荐使用的意思,没有用更多的客户端做对比。下面以weechat为例,来写一下基本的使用命令。 安装weechat:Mac里面用 brewin... 查看详情
golang之一个简单的聊天机器人
翠花,上代码packagemainimport("bufio""fmt""os""strings")funcmain(){//从标准输入读取数据inputReader:=bufio.NewReader(os.Stdin)fmt.Println("Pleaseinputyourname:")//读取数据直到遇见
位置input,err:=inputReader.ReadString(‘
‘)if 查看详情
如何使用 Python Twitch IRC Bot 获取聊天消息参数?
...我的PythonTwitchIRCBot使用套接字接收和处理消息命令参数的简单方法。例如,如果我要设置歌曲请求,并且聊天中的用户输入“ 查看详情
一个基于vb的简单irc机器人服务器-genebot&evilbot
...时候的设想。现在实现了。之前用python的irc框架sopel写过一个机器人,但在windows上运行诸多不便。VB看似被众多“大佬”嘲笑,但是简单的windows图形界面快速编程远胜过qt。下面贴几张图:效果图(还 查看详情
golang获取命令行参数(代码片段)
部署golang项目时难免要通过命令行来设置一些参数,那么在golang中如何操作命令行参数呢?可以使用os库和flag库。 1、golangos库获取命令行参数os可以通过变量Args来获取命令参数,os.Args返回一个字符串数组,其中第一个参数... 查看详情
设计模式这样玩泰简单(golang版)-命令模式(代码片段)
场景老板:我们有一个业务的组件实现是第三方,他们暴露的接口非常细粒度,我们要根据不同的接口组成一个指令,并且指令能复用,你有什么好的方案你:好的,老板,那就使用命令模式方案命令模式,就是利用一些实现同一接口的对象... 查看详情
在c++中,如何用不同长度的字符串替换一个命令行参数。(代码片段)
我有一个大型的C++程序,在这个程序中,可以使用以下方法提供几个命令行参数char*argv[].在程序的后面,第一个参数需要用一个新的任意长度的字符串代替。我首先尝试用简单的方法来实现。MyProg_1.cpp#include<cstring>#include<i... 查看详情
支持 IRC 后端的 Ajax 聊天前端
...络聊天解决方案。基本上我有自己的IRC服务器。我想配置一个ajax网络聊天解决方案来连接它。我在Google中发现了大量的ajax网络聊天解决方案。但是没有一个(除了不是开源的mibbit)符合我的标准。你知道吗?如果没 查看详情