300行代碼實現(xiàn)go語言即時通訊聊天室_第1頁
300行代碼實現(xiàn)go語言即時通訊聊天室_第2頁
300行代碼實現(xiàn)go語言即時通訊聊天室_第3頁
300行代碼實現(xiàn)go語言即時通訊聊天室_第4頁
300行代碼實現(xiàn)go語言即時通訊聊天室_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第300行代碼實現(xiàn)go語言即時通訊聊天室學了2年Java,因為工作原因需要轉Golang,3天時間學習了下go的基本語法,做這樣一個聊天室小項目來鞏固串聯(lián)一下語法。

實現(xiàn)的功能:公聊,私聊,修改用戶名

只用到了四個類:

main.go:用來啟動服務器server.go:服務器相關代碼client.go:客戶端相關代碼,用戶可以直接操作的可視化界面user.go:用戶類,用來封裝用戶的業(yè)務邏輯

架構圖

server.go

packagemain

import(

"fmt"

"io"

"net"

"sync"

"time"

typeServerstruct{

Ipstring

Portint

//在線用戶列表

OnlineMapmap[string]*User

mapLocksync.RWMutex

//消息廣播的Channel

Messagechanstring

funcNewServer(ipstring,portint)*Server{

server:=Server{

Ip:ip,

Port:port,

OnlineMap:make(map[string]*User),

Message:make(chanstring),

returnserver

func(s*Server)Handler(connnet.Conn){

//業(yè)務邏輯

//fmt.Println("鏈接建立成功")

user:=NewUser(conn,s)

user.Online()

//監(jiān)聽用戶是否活躍

isLive:=make(chanbool)

gofunc(){

buf:=make([]byte,4096)

for{

n,error:=conn.Read(buf)

ifn==0{

user.Offline()

return

iferror!=nilerror!=io.EOF{

fmt.Println("readerror")

msg:=string(buf[:n-1])

user.DoMessage(msg)

//表示用戶活躍

isLive-true

for{

select{

case-isLive:

//當前用戶活躍,不做任何時,激活select,重置定時器

case-time.After(time.Second*300):

//超時,將user強制關閉

user.SendMsg("你被踢了")

close(user.C)

conn.Close()

return

func(s*Server)ListenMessager(){

for{

msg:=-s.Message

s.mapLock.Lock()

for_,user:=ranges.OnlineMap{

user.C-msg

s.mapLock.Unlock()

func(s*Server)BroadCast(user*User,msgstring){

sendMsg:="["+user.Addr+"]"+user.Name+":"+msg

s.Message-sendMsg

func(s*Server)Start(){

listener,error:=net.Listen("tcp",fmt.Sprintf("%s:%d",s.Ip,s.Port))

iferror!=nil{

fmt.Println("listenererror...")

return

deferlistener.Close()

gos.ListenMessager()

for{

conn,error:=listener.Accept()

iferror!=nil{

fmt.Println("accepterror...")

continue

gos.Handler(conn)

client.go

packagemain

import(

"flag"

"fmt"

"io"

"net"

"os"

typeClientstruct{

ServerIpstring

ServerPortint

Namestring

connnet.Conn

flagint

funcNewClient(serverIpstring,serverPortint)*Client{

client:=Client{

ServerIp:serverIp,

ServerPort:serverPort,

flag:9999,

conn,error:=net.Dial("tcp",fmt.Sprintf("%s:%d",serverIp,serverPort))

iferror!=nil{

fmt.Println("netdialerror...")

returnnil

client.conn=conn

returnclient

func(c*Client)menu()bool{

varflagint

fmt.Println("1.公聊模式")

fmt.Println("2.私聊模式")

fmt.Println("3.修改用戶名")

fmt.Println("0.退出")

fmt.Scanln(flag)

ifflag=0flag=3{

c.flag=flag

returntrue

}else{

fmt.Println("請輸入合法數(shù)字")

returnfalse

//修改用戶名

func(c*Client)UpdateName()bool{

fmt.Println("請輸入用戶名")

fmt.Scanln(c.Name)

sendMsg:="rename|"+c.Name+"\n"

_,error:=c.conn.Write([]byte(sendMsg))

iferror!=nil{

fmt.Println("conn.writeerror...")

returnfalse

returntrue

func(c*Client)PublicChat(){

varchatMsgstring

fmt.Println("請輸入聊天內容,輸入exit退出")

fmt.Scanln(chatMsg)

forchatMsg!="exit"{

iflen(chatMsg)!=0{

msg:=chatMsg+"\n"

_,error:=c.conn.Write([]byte(msg))

iferror!=nil{

fmt.Println("conn.Writeerror....")

break

chatMsg=""

fmt.Println("請輸入聊天內容,輸入exit退出")

fmt.Scanln(chatMsg)

func(c*Client)PrivateChat(){

varremoteUserstring

varchatMsgstring

c.SelectUsers()

fmt.Println("請輸入聊天對象的用戶名,輸入exit退出")

fmt.Scanln(remoteUser)

forremoteUser!="exit"{

fmt.Println("請輸入聊天內容,輸入exit退出")

fmt.Scanln(chatMsg)

forchatMsg!="exit"{

iflen(chatMsg)!=0{

msg:="to|"+remoteUser+"|"+chatMsg+"\n\n"

_,error:=c.conn.Write([]byte(msg))

iferror!=nil{

fmt.Println("conn.Writeerror....")

break

chatMsg=""

fmt.Println("請輸入聊天內容,輸入exit退出")

fmt.Scanln(chatMsg)

c.SelectUsers()

remoteUser=""

fmt.Println("請輸入聊天對象的用戶名,輸入exit退出")

fmt.Scanln(remoteUser)

//查詢在線用戶

func(c*Client)SelectUsers(){

sendMsg:="who\n"

_,error:=c.conn.Write([]byte(sendMsg))

iferror!=nil{

fmt.Println("conn.Writeerror....")

return

//處理server返回的消息

func(c*Client)DealResponse(){

io.Copy(os.Stdout,c.conn)

func(c*Client)Run(){

forc.flag!=0{

forc.menu()!=true{

switchc.flag{

case1:

//公聊

c.PublicChat()

case2:

//私聊

c.PrivateChat()

case3:

//修改用戶名

c.UpdateName()

varserverIpstring

varserverPortint

funcinit(){

flag.StringVar(serverIp,"ip","","設置服務器IP地址(默認為)")

flag.IntVar(serverPort,"port",8888,"設置服務器端口(默認為8888)")

funcmain(){

flag.Parse()

client:=NewClient(serverIp,serverPort)

ifclient==nil{

fmt.Println("鏈接服務器失敗")

return

goclient.DealResponse()

fmt.Println("鏈接服務器成功")

client.Run()

user.go

packagemain

import(

"net"

"strings"

typeUserstruct{

Namestring

Addrstring

Cchanstring

connnet.Conn

server*Server

funcNewUser(connnet.Conn,server*Server)*User{

userAddr:=conn.RemoteAddr().String()

user:=User{

Name:userAddr,

Addr:userAddr,

C:make(chanstring),

conn:conn,

server:server,

gouser.ListenMessage()

returnuser

//用戶上線

func(u*User)Online(){

u.server.mapLock.Lock()

u.server.OnlineMap[u.Name]=u

u.server.mapLock.Unlock()

u.server.BroadCast(u,"上線")

//用戶下線

func(u*User)Offline(){

u.server.mapLock.Lock()

delete(u.server.OnlineMap,u.Name)

u.server.mapLock.Unlock()

u.server.BroadCast(u,"下線")

//給當前user的客戶端發(fā)送消息

func(u*User)SendMsg(msgstring){

u.conn.Write([]byte(msg))

//處理消息

func(u*User)DoMessage(msgstring){

ifmsg=="who"{

//查詢當前在線用戶

u.server.mapLock.Lock()

for_,user:=rangeu.server.OnlineMap{

onlineMsg:="["+user.Addr+"]"+user.Name+":在線...\n"

u.SendMsg(onlineMsg)

u.server.mapLock.Unlock()

}elseiflen(msg)7msg[:7]=="rename|"{

//修改用戶名rename|xxx

newName:=strings.Split(msg,"|")[1]

//判斷名字是否已經存在

_,ok:=u.server.OnlineMap[newName]

ifok{

u.SendMsg("用戶名已存在\n")

}else{

u.server.mapLock.Lock()

delete(u.server.OnlineMap,u.Name)

u.server.OnlineMap[newName]=u

u.server.mapLock.Unlock()

u.Name=newName

u.SendMsg

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論