【Go基础】搭建TCP服务端、客户端

搭建TCP服务端、客户端


TCP基础介绍

  TCP协议(Transmission Control Protocol)是一个安全、可靠、稳定、有序的数据报传输协议。如果说网络层(通过ip地址)解决了主机识别的问题,那么TCP协议则是(通过端口号)解决了如何识别主机上唯一一个进程的问题。

  TCP还定义数据报的请求序号和确认序号,以确保消息的准确有序。

  TCP通过三次握手、四次挥手,保障传输的安全性。
在这里插入图片描述

服务端Listen函数

Listen函数:

func Listen(network, address string) (Listener, error)

  • network:网络类型,可以填写tcpudp

  • address:设定服务器地址,格式为[ip]:端口, ip可以省略,缺省默认值为0.0.0.0

  • error:返回nil代表无错误,否者存在错误

  • Listener:监听者对象,用于后续的步骤处理

    • Listener
    // A Listener is a generic network listener for stream-oriented protocols.
    //
    // Multiple goroutines may invoke methods on a Listener simultaneously.
    type Listener interface {
    	// Accept waits for and returns the next connection to the listener.
    	Accept() (Conn, error)
    
    	// Close closes the listener.
    	// Any blocked Accept operations will be unblocked and return errors.
    	Close() error
    
    	// Addr returns the listener's network address.
    	Addr() Addr
    }
    
    • Listener#Accept返回的Conn
    // Conn is a generic stream-oriented network connection.
    //
    // Multiple goroutines may invoke methods on a Conn simultaneously.
    type Conn interface {
    	// Read reads data from the connection.
    	// Read can be made to time out and return an error after a fixed
    	// time limit; see SetDeadline and SetReadDeadline.
    	Read(b []byte) (n int, err error)
    
    	// Write writes data to the connection.
    	// Write can be made to time out and return an error after a fixed
    	// time limit; see SetDeadline and SetWriteDeadline.
    	Write(b []byte) (n int, err error)
    
    	// Close closes the connection.
    	// Any blocked Read or Write operations will be unblocked and return errors.
    	Close() error
    
    	// LocalAddr returns the local network address.
    	LocalAddr() Addr
    
    	// RemoteAddr returns the remote network address.
    	RemoteAddr() Addr
    
    	// SetDeadline sets the read and write deadlines associated
    	// with the connection. It is equivalent to calling both
    	// SetReadDeadline and SetWriteDeadline.
    	//
    	// A deadline is an absolute time after which I/O operations
    	// fail instead of blocking. The deadline applies to all future
    	// and pending I/O, not just the immediately following call to
    	// Read or Write. After a deadline has been exceeded, the
    	// connection can be refreshed by setting a deadline in the future.
    	//
    	// If the deadline is exceeded a call to Read or Write or to other
    	// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
    	// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
    	// The error's Timeout method will return true, but note that there
    	// are other possible errors for which the Timeout method will
    	// return true even if the deadline has not been exceeded.
    	//
    	// An idle timeout can be implemented by repeatedly extending
    	// the deadline after successful Read or Write calls.
    	//
    	// A zero value for t means I/O operations will not time out.
    	SetDeadline(t time.Time) error
    
    	// SetReadDeadline sets the deadline for future Read calls
    	// and any currently-blocked Read call.
    	// A zero value for t means Read will not time out.
    	SetReadDeadline(t time.Time) error
    
    	// SetWriteDeadline sets the deadline for future Write calls
    	// and any currently-blocked Write call.
    	// Even if write times out, it may return n > 0, indicating that
    	// some of the data was successfully written.
    	// A zero value for t means Write will not time out.
    	SetWriteDeadline(t time.Time) error
    }
    

客户端Dial函数

Dial函数:

func Dial(network, address string) (Conn, error)

  • network:网络类型,可以填写tcpudp

  • address:设定服务器地址,格式为[ip]:端口, ip可以省略,缺省默认值为0.0.0.0

  • error:返回nil代表无错误,否者存在错误

  • Conn:和服务端通信的连接对象。

    注:Conn对象的具体信息上文已经给出,这里不再赘述。

搭建TCP服务端、客户端示例

  • TCP服务端
import (
	"fmt"
	"log"
	"net"
)

func main() {
	// 1. 绑定ip和端口,设置监听
	listener, err := net.Listen("tcp", "localhost:8888")
	if err != nil {
		log.Panic("Failed to Listen", err)
	}
	// 延迟关闭,释放资源
	defer listener.Close()

	// 2. 循环等待新连接
	for {
		// 从连接列表获取新连接
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("Failed to Accept", err)
		}
		// 3. 与新连接通信(为了不同步阻塞,这里开启异步协程进行函数调用)
		go handle_conn(conn)
	}
}

/**
 * 处理连接
 */
func handle_conn(conn net.Conn) {
	defer conn.Close()
	fmt.Println("New connection ", conn.RemoteAddr())
	// 通信
	buf := make([]byte, 256)
	for {
		// 从网络中读
		readBytesCount, err := conn.Read(buf)
		if err != nil {
			fmt.Println("Failed to read", err)
			break
		}
		// 提示:buf[:n]的效果为:读取buf[总长度-n]至buf[n]处的字节
		fmt.Println("服务端收到数据:\t", string(buf[:readBytesCount]))

		// 写回网络 -- 收到什么就写回什么,即:回射服务器
		writeByteCount, err := conn.Write(buf[:readBytesCount])
		if err != nil {
			fmt.Println("Failed to write", err)
			break
		}
		fmt.Printf("write success %d bytes\n", writeByteCount)
	}
}
  • TCP客户端
import (
	"fmt"
	"net"
	"os"
)

func main() {
	// 1. 建立连接
	conn, err := net.Dial("tcp", "localhost:8888")
	if err != nil {
		fmt.Println("Failed to Dial")
		return
	}
	// 延迟关闭,释放资源
	defer conn.Close()

	// 2. 与服务端通信
	buf := make([]byte, 256)
	for {
		// 2.1 从控制台读取输入
		readBytesCount, _ := os.Stdin.Read(buf)
		// 2.2 写到网络(即:发送请求)
		conn.Write(buf[:readBytesCount])
		// 2.3 读网络(即:获取响应)
		readBytesCount, _ = conn.Read(buf)
		// 2.4 输出到控制台
		// 提示:buf[:n]的效果为:读取buf[总长度-n]至buf[n]处的字节
		os.Stdout.Write(buf[:readBytesCount])
	}
}
  • 通信测试

先启动server端,再启动client端,然后在client端的控制台进行任意输入触发进行TCP请求,

  1. 在server端控制台,可看到来自client的请求信息
    xx
  2. 在client端控制台,可看到来自server端的响应信息
    在这里插入图片描述


^_^ 整理自《Go语言区块链应用开发从入门到精通》高野 编著

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt是一个跨平台的C++应用程序框架,它提供了丰富的库和工具来帮助开发者创建各种类型的应用程序,包括网络通信应用。 在Qt中实现TCP服务端客户端的通信非常简单。首先,我们需要创建一个QTcpServer对象来作为服务端,该对象负责监听客户端的连接请求。接下来,我们需要为QTcpServer对象绑定一个IP地址和端口号,以便客户端能够连接到该地址和端口。当有新的客户端连接时,QTcpServer对象会发出newConnection()信号。 在服务端的槽函数中,我们可以使用QTcpServer的nextPendingConnection()函数获取新连接的QTcpSocket对象,该对象用于和客户端进行通信。我们可以在该对象上发送和接收数据,以实现服务端客户端之间的数据交互。 接下来,我们需要创建一个QTcpSocket对象作为客户端,该对象负责和服务端建立连接。我们需要使用connectToHost()函数来指定要连接的服务端的IP地址和端口号。一旦连接成功,QTcpSocket对象会发出connected()信号。 在客户端的槽函数中,我们可以使用QTcpSocket对象发送和接收数据。我们可以使用write()函数发送数据,使用readyRead()信号和read()函数接收数据。 通过这种方式,我们可以在服务端客户端之间进行双向的数据通信。服务端可以同时接受多个客户端的连接,每个客户端都可以和服务端进行独立的数据交互。 总的来说,使用Qt实现TCP服务端客户端通信非常方便。通过使用QTcpServer和QTcpSocket类,我们可以轻松地建立连接,发送和接收数据。这种通信方式可以应用于多种场景,如实时聊天、远程控制等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值