package main
import (
"fmt"
"net"
"strings"
"os"
"log"
)
// 服務(wù)器只是中轉(zhuǎn)!
var msgQue = make(chan string, 1000) // 現(xiàn)在處理一個(gè)消息隊(duì)列
var quitChan = make(chan bool) // 管理退出消息
var onlineConns = make(map[string]net.Conn) // 管理連接
var logfile *os.File
var logger *log.Logger
func ProcessInfo(conn net.Conn) {
buf := make([]byte, 1024)
defer func(conn net.Conn) {
addr := fmt.Sprintf("%s",conn.RemoteAddr())
delete(onlineConns,addr) // 把斷開的鏈接從字典中去掉
conn.Close()
for i := range onlineConns{ // 打印一下
fmt.Println("online"+i)
}
}(conn)
for {
numofbyte, err := conn.Read(buf) // 讀數(shù)據(jù)并賦值
if err != nil {
break // 報(bào)錯(cuò)退出
}
if numofbyte != 0 { // 讀到了數(shù)據(jù)長度如果不等于0
msg := string(buf[:numofbyte]) //打印數(shù)據(jù),注意之前發(fā)的數(shù)據(jù)因?yàn)楦牡氖荹]byte,存在未被覆蓋的字節(jié)信息,所以這里切一下
msgQue <- msg // 這里放到channel中
}
}
}
func Checkerror1(err error) {
if err != nil {
panic(err)
}
}
func doProcessMessage(mesa string){
content := strings.Split(mesa,"#") // 把字符串ip序號#消息進(jìn)行分割
if len(content) >1 { //如果有消息
addr := content[0]
sendMessage := strings.Join(content[1:],"#") // 這里為了防止消息中有另外的#
if conn,ok := onlineConns[addr]; ok{ // 看是前面的ip否在消息隊(duì)列中
_, err := conn.Write([]byte(sendMessage)) //如果在的話寫入
if err != nil{
fmt.Println("wrong")
}
}
}
}
func ConsumeMessage() { // 這個(gè)consume用select用來監(jiān)控兩個(gè)channel如果quitchan有消息就退出,如果不是就處理消息進(jìn)行分發(fā)
for {
select {
case mssage := <-msgQue: //解析
doProcessMessage(mssage) // 消息處理,并進(jìn)行分發(fā)
case <-quitChan:
break
}
}
}
func main() {
logfile, err := os.OpenFile("LOG_DIRECORY", os.O_RDWR|os.O_CREATE,0) // 打開文件
if err != nil{
fmt.Println("log file create failure!")
os.Exit(-1)
}
defer logfile.Close()
logger = log.New(logfile,"\r\n",log.Ldate|log.Ltime|log.Llongfile)
logger.Println("llkjklj") // 輸入log
listen_s, err := net.Listen("tcp", "127.0.0.1:8080") // 開啟一個(gè)socket
Checkerror1(err)
defer listen_s.Close() // 結(jié)束關(guān)socket
fmt.Println("server is waiting..")
go ConsumeMessage()
for {
conn, err := listen_s.Accept() // socket 接鏈接
Checkerror1(err)
addr := fmt.Sprintf("%s",conn.RemoteAddr()) // 把這個(gè)轉(zhuǎn)換一下到string中
onlineConns[addr] = conn
go ProcessInfo(conn) // 處理數(shù)據(jù)
}
}
![]()
package main
import (
"fmt"
"net"
"bufio"
"os"
"strings"
)
func MessageSend(conn net.Conn) {
var input string
for {
reader := bufio.NewReader(os.Stdin) // 標(biāo)準(zhǔn)輸入
data, _,_ := reader.ReadLine() // 讀到數(shù)據(jù)到data
input = string(data)
if strings.ToUpper(input) == "EXIT" { // 如果寫的是exit就退出
conn.Close()
break
}
_, err := conn.Write([]byte(input)) // 發(fā)消息
if err != nil { // 報(bào)錯(cuò)退出
conn.Close()
fmt.Println("Clinet connect fail")
break
}
}
}
func Checkerror( err error){
if err != nil {
panic(err)
}
}
func main(){
conn, err := net.Dial("tcp","127.0.0.1:8080") // 連接socket
Checkerror(err)
defer conn.Close()
MessageSend(conn) // 發(fā)消息
buf := make([]byte,1024)
for {
_, err := conn.Read(buf) // 讀消息
if err != nil{
fmt.Println("exit")
os.Exit(0) // 正常退出
}
fmt.Println(string(buf))
}
}
客戶端