mirror of
https://github.com/MADTeacher/go_basics.git
synced 2025-11-29 05:36:55 +02:00
Глава 8
Допричесать игру
This commit is contained in:
77
part_8/8.3/tcp-chat/client/client.go
Normal file
77
part_8/8.3/tcp-chat/client/client.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var waitingGr sync.WaitGroup
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func sendMessage(connection net.Conn, waitingGr *sync.WaitGroup) {
|
||||
defer waitingGr.Done()
|
||||
for {
|
||||
reader := bufio.NewReader(os.Stdin) // считываем введенное сообщение
|
||||
text, _ := reader.ReadString('\n')
|
||||
|
||||
if strings.TrimSuffix(strings.TrimSpace(text), "\r\n") == "/stop" {
|
||||
// завершение работы клиента
|
||||
break
|
||||
} else {
|
||||
_, err := connection.Write([]byte(text))
|
||||
checkErr(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func receiveMessage(connection net.Conn, waitingGr *sync.WaitGroup) {
|
||||
defer waitingGr.Done()
|
||||
for {
|
||||
// ждем сообщение от сервера и считываем его
|
||||
message, err := bufio.NewReader(connection).ReadString('\n')
|
||||
|
||||
if err == io.EOF {
|
||||
fmt.Println("Connection close!")
|
||||
break
|
||||
} else if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
break
|
||||
}
|
||||
|
||||
message = message[:len(message)-1] // обрезаем символ перевода на следующую строку
|
||||
fmt.Println(string(message))
|
||||
}
|
||||
}
|
||||
|
||||
func RunClient(port int) {
|
||||
// запускает реализацию клиента TCP и соединяет вас с нужным TCP-сервером
|
||||
connection, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf("The TCP server is %s\n", connection.RemoteAddr().String())
|
||||
defer connection.Close()
|
||||
|
||||
waitingGr.Add(1)
|
||||
|
||||
fmt.Println("Enter name: ")
|
||||
temp := bufio.NewReader(os.Stdin)
|
||||
userName, _ := temp.ReadString('\n')
|
||||
_, err = connection.Write([]byte(userName))
|
||||
checkErr(err)
|
||||
|
||||
go sendMessage(connection, &waitingGr)
|
||||
go receiveMessage(connection, &waitingGr)
|
||||
|
||||
waitingGr.Wait()
|
||||
}
|
||||
3
part_8/8.3/tcp-chat/go.mod
Normal file
3
part_8/8.3/tcp-chat/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module tcp/server
|
||||
|
||||
go 1.24
|
||||
38
part_8/8.3/tcp-chat/main.go
Normal file
38
part_8/8.3/tcp-chat/main.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"tcp/server/client"
|
||||
"tcp/server/server"
|
||||
)
|
||||
|
||||
const PORT = 8081
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("You didn't select a launch option!!!")
|
||||
return
|
||||
}
|
||||
numGR, err := strconv.Atoi(os.Args[1])
|
||||
checkErr(err)
|
||||
|
||||
switch numGR {
|
||||
case 1:
|
||||
fmt.Println("Server is running")
|
||||
server.RunServer(PORT)
|
||||
case 2:
|
||||
fmt.Println("Client is running")
|
||||
client.RunClient(PORT)
|
||||
default:
|
||||
log.Fatal("What pokemon is this?")
|
||||
}
|
||||
}
|
||||
85
part_8/8.3/tcp-chat/server/server.go
Normal file
85
part_8/8.3/tcp-chat/server/server.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
var connections []net.Conn
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleConnection(connection net.Conn) {
|
||||
connections = append(connections, connection)
|
||||
userName, _ := bufio.NewReader(connection).ReadString('\n')
|
||||
userName = userName[:len(userName)-2]
|
||||
_, err := connection.Write([]byte("Hi " + userName + "\n"))
|
||||
checkErr(err)
|
||||
|
||||
for {
|
||||
text, err := bufio.NewReader(connection).ReadString('\n')
|
||||
if err != nil {
|
||||
connection.Close()
|
||||
removeConnection(connection)
|
||||
broadCastMessage(userName+" is offline\n", connection)
|
||||
break
|
||||
}
|
||||
|
||||
broadCastMessage(userName+":"+text, connection)
|
||||
}
|
||||
}
|
||||
|
||||
func removeConnection(connection net.Conn) {
|
||||
var i int
|
||||
|
||||
for i = range connections {
|
||||
if connections[i] == connection {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(connections) > 1 {
|
||||
connections = append(connections[:i], connections[i+1:]...)
|
||||
} else {
|
||||
connections = nil
|
||||
}
|
||||
}
|
||||
|
||||
func broadCastMessage(msg string, connection net.Conn) {
|
||||
// отправка сообщения всем клиентам
|
||||
for _, c := range connections {
|
||||
if connection != c {
|
||||
_, err := c.Write([]byte(msg))
|
||||
checkErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
msg = msg[:len(msg)-1]
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
func RunServer(port int) {
|
||||
// net.Listen возвращает Listener переменную,
|
||||
// которая является общим сетевым прослушивателем для потоковых протоколов
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||
checkErr(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
for {
|
||||
connection, err := listener.Accept() // ожидание подключения клиента к серверу
|
||||
// Только после успешного вызова Accept()TCP-сервер может начать
|
||||
// взаимодействовать с TCP-клиентами
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
go handleConnection(connection)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user