go语言实现客户端和服务端收发信息 网络编程、异常处理、函数、io读写等综合应用

代码示例评论阅读13分6秒

下面将提供一个简单的TCP客户端和服务端的Go语言实现,包含网络编程、异常处理、函数和IO读写等基础概念。

服务端代码:文章源自Golang编程指南-https://www.va26.com/work/348.html

package main  
  
import (  
	"bufio"  
	"fmt"  
	"io"  
	"net"  
	"os"  
)  
  
func main() {  
	listener, err := net.Listen("tcp", ":8080")  
	if err != nil {  
		fmt.Println("Error listening:", err.Error())  
		os.Exit(1)  
	}  
	defer listener.Close()  
  
	fmt.Println("Server is listening on port 8080...")  
  
	for {  
		conn, err := listener.Accept()  
		if err != nil {  
			fmt.Println("Error accepting:", err.Error())  
			continue  
		}  
		go handleConnection(conn)  
	}  
}  
  
func handleConnection(conn net.Conn) {  
	defer conn.Close()  
  
	reader := bufio.NewReader(conn)  
	for {  
		message, err := reader.ReadString('\n')  
		if err != nil {  
			if err == io.EOF {  
				fmt.Println("Client disconnected")  
			} else {  
				fmt.Println("Error reading:", err.Error())  
			}  
			break  
		}  
  
		fmt.Print("Message received:", message)  
		conn.Write([]byte("Message received.\n"))  
	}  
}

客户端代码:文章源自Golang编程指南-https://www.va26.com/work/348.html

package main  
  
import (  
	"bufio"  
	"fmt"  
	"net"  
	"os"  
	"strings"  
)  
  
func main() {  
	conn, err := net.Dial("tcp", "localhost:8080")  
	if err != nil {  
		fmt.Println("Error connecting:", err.Error())  
		os.Exit(1)  
	}  
	defer conn.Close()  
  
	reader := bufio.NewReader(os.Stdin)  
	for {  
		fmt.Print("Enter message: ")  
		message, err := reader.ReadString('\n')  
		if err != nil {  
			fmt.Println("Error reading:", err.Error())  
			break  
		}  
  
		message = strings.TrimSpace(message)  
		if message == "exit" {  
			break  
		}  
  
		conn.Write([]byte(message + "\n"))  
  
		serverResponse, err := bufio.NewReader(conn).ReadString('\n')  
		if err != nil {  
			fmt.Println("Error reading from server:", err.Error())  
			break  
		}  
  
		fmt.Print("Server response:", serverResponse)  
	}  
}

代码解释:文章源自Golang编程指南-https://www.va26.com/work/348.html

1、服务端监听在8080端口,并等待客户端的连接。文章源自Golang编程指南-https://www.va26.com/work/348.html

2、每当有一个新的连接时,服务端会启动一个新的goroutine来处理该连接,以便同时处理多个客户端。文章源自Golang编程指南-https://www.va26.com/work/348.html

3、客户端通过TCP连接到服务端,并可以发送消息。输入“exit”可以关闭客户端。文章源自Golang编程指南-https://www.va26.com/work/348.html

4、服务端读取客户端发送的消息,打印到控制台,并回复一条确认消息。文章源自Golang编程指南-https://www.va26.com/work/348.html

5、服务端和客户端都使用了bufio.Reader来读取流数据,它提供了缓冲IO以提高效率。文章源自Golang编程指南-https://www.va26.com/work/348.html

6、在读取和写入数据时,都包含了对异常的处理,确保程序的健壮性。文章源自Golang编程指南-https://www.va26.com/work/348.html

为了简化这个示例,这里没有包含更复杂的错误处理和协议设计。在生产环境中,可能还需要添加身份验证、加密通信、超时处理、流量控制等特性。文章源自Golang编程指南-https://www.va26.com/work/348.html

运行服务端和客户端之前,请确保它们在同一台机器上,或者客户端连接地址正确指向了服务端的公开IP和端口。运行服务端后,可以打开另一个终端窗口运行客户端,并进行交互。

下面是一个更复杂的TCP服务器和客户端的示例,这个示例包含更多的特性和错误处理。

服务器端代码

package main  
  
import (  
	"bufio"  
	"fmt"  
	"io"  
	"net"  
	"sync"  
)  
  
type Client struct {  
	conn    net.Conn  
	name    string  
	ch      chan string // 用于接收客户端消息的通道  
	wg      *sync.WaitGroup  
	quit    chan bool  
}  
  
var (  
	entering = make(chan *Client)  
	leaving  = make(chan *Client)  
	messages = make(chan string) // 所有接收到的客户端消息  
)  
  
func main() {  
	listener, err := net.Listen("tcp", "localhost:8080")  
	if err != nil {  
		fmt.Println("Error listening:", err.Error())  
		return  
	}  
	fmt.Println("Server is listening on localhost:8080...")  
  
	var wg sync.WaitGroup  
	wg.Add(1)  
	go broadcaster(&wg)  
  
	for {  
		conn, err := listener.Accept()  
		if err != nil {  
			fmt.Println("Error accepting:", err.Error())  
			continue  
		}  
		go handleConn(conn, &wg)  
	}  
  
	wg.Wait()  
}  
  
func broadcaster(wg *sync.WaitGroup) {  
	defer wg.Done()  
	clients := make(map[*Client]bool)  
	for {  
		select {  
		case msg := <-messages:  
			// 向所有客户端广播消息  
			for cli := range clients {  
				cli.ch <- msg  
			}  
		case cli := <-entering:  
			clients[cli] = true  
		case cli := <-leaving:  
			delete(clients, cli)  
			close(cli.ch)  
		}  
	}  
}  
  
func handleConn(conn net.Conn, wg *sync.WaitGroup) {  
	defer conn.Close()  
	ch := make(chan string)  
	go clientWriter(conn, ch, wg)  
  
	input := bufio.NewScanner(conn)  
	wg.Add(1)  
	go func() {  
		defer wg.Done()  
		cli := &Client{conn, conn.RemoteAddr().String(), ch, wg, make(chan bool)}  
		ch <- "You are " + cli.name  
		messages <- cli.name + " has arrived"  
		entering <- cli  
  
		for input.Scan() {  
			messages <- cli.name + ": " + input.Text()  
		}  
  
		leaving <- cli  
		messages <- cli.name + " has left"  
		conn.Close()  
	}()  
}  
  
func clientWriter(conn net.Conn, ch <-chan string, wg *sync.WaitGroup) {  
	defer wg.Done()  
	for msg := range ch {  
		_, err := fmt.Fprintln(conn, msg)  
		if err != nil {  
			fmt.Println("Error writing to", conn.RemoteAddr(), ":", err.Error())  
			return  
		}  
	}  
}

客服端代码

package main  
  
import (  
	"bufio"  
	"fmt"  
	"net"  
	"os"  
	"strings"  
)  
  
func main() {  
	conn, err := net.Dial("tcp", "localhost:8080")  
	if err != nil {  
		fmt.Println("Error connecting:", err.Error())  
		return  
	}  
	defer conn.Close()  
  
	go messageReader(conn)  
  
	scanner := bufio.NewScanner(os.Stdin)  
	for scanner.Scan() {  
		text := scanner.Text()  
		if strings.ToLower(text) == "/quit" {  
			break  
		}  
		_, err := fmt.Fprintf(conn, text+"\n")  
		if err != nil {  
			fmt.Println("Error sending message:", err.Error())  
			break  
		}  
	}  
}  
  
func messageReader(conn net.Conn) {  
	reader := bufio.NewReader(conn)  
	for {  
		message, err := reader.ReadString('\n')  
		if err != nil {  
			fmt.Println("Connection closed by server.")  
			return  
		}  
		fmt.Print(message)  
	}  
}

这个更复杂的示例中,服务器端可以处理多个并发的客户端连接,并且可以广播消息到所有连接的客户端。客户端可以发送消息到服务器,并且接收来自服务器的广播消息。客户端输入“/quit”命令可以安全地退出程序。服务器端通过goroutines和channels管理客户端的连接和消息广播,确保了高效的并发处理。

 
  • 本文由golang编程指南作者原创,请勿恶意转载!
  • 转载请务必保留本文链接:https://www.va26.com/work/348.html
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证