golang实现简单的tcp数据传输

目录
  • 前言
    • 首先介绍什么是Tcp协议
    • 什么是可靠数据传输?
    • TCP的快速重传机制
  • 简单介绍TCP连接的三次握手和四次挥手
    • 三次握手
    • 四次挥手
  • golang实现简单的tcp连接建立
    • 服务端
    • 完整代码
    • 客户端
    • 完整代码

前言

通过golang实现Tcp的连接与信息传输

本文主要介绍Tcp协议以及如何使用golang来建立一个简单的tcp连接服务,并且实现信息的传输。

首先介绍什么是Tcp协议

Tcp协议是传输层的一个可靠数据传输协议,Tcp协议有以下几个特点:

  • 点对点的发送:一个发送方,一个接收方
  • 可靠性: 可靠的、按序的字节流
  • 流水线机制:TCP拥塞控制和流量控制机制设置滑动窗口尺寸
  • 缓存窗口: 发送方/接收方可以进行缓存
  • 全双工:同一连接中能够传输双向数据流
  • 面向连接:通信双方在发送数据之前必须建立连接,在建立连接之后才能进行数据传输
    • 连接状态只在连接的两端中维护,在沿途节点中并不维护状态(端到端)
    • TCP连接包括:两台主机上的缓存、连接状态变量、socket等(双方都要维护)

什么是可靠数据传输?

TCP在IP层提供的不可靠服务基础上实现的可靠数据传输服务,基于流水线机制。当有发送端的数据丢失后,接收端不会不予理睬,而是重新会发送给发送方一个信号,请求重新发送该数据报。以此来确保数据的可靠性传输。这里只作简单解释可靠数据传输的特点:

  • 累计确认机制:当接收方接收到因为超时重传的帧后,会传输当前累加后的(最大的)ACK序号。
  • TCP使用单一重传定时器(也就是SR定时器,只判断ACK的那个帧进行定时处理)
  • 触发重传的事件:超时、收到重复ACK
  • 渐进式:暂不考虑重复ACK、暂不考虑流量控制、暂不考虑拥塞控制

TCP的快速重传机制

如果TCP通道建立之后,数据在发送过程中丢失。TCP将会触发快速重传机制,下面是快速重传机制的特点:

  • 如果发生超时情况,而超时时间间隔过长,则需要等待很长时间。
  • 当发送方接收到3个重复的ACK,就触发快速重传机制,直接重新发送这个帧数据。

简单介绍TCP连接的三次握手和四次挥手

三次握手

  • 客户端希望与服务端建立TCP连接时,需要先发送一个SYN请求报文段给服务端,并告诉服务端自己的初始报文段序列号是多少。
  • 服务端接收到这个报文后进行随机选择初始的报文段序列号,分配滑动窗口缓存空间大小。接着返回一个SYNACK响应报文段并且把服务端初始报文段序列号和滑动窗口缓存空间大小给客户端表明我已经接到你的请求了。
  • 客户端接收到SYNACK报文段后会答复一个ACK报文段表明我已经收到,可以建立连接了。同时会根据接收到的服务端的滑动窗口缓存空间大小,分配一个同样大小的滑动窗口缓存空间用于发送。

四次挥手

  • 客户端进程发出连接释放的报文FIN=1以及一个客户端的序列号(该序列号等于最后一个传进来的数据的序列号+1)给服务端,并进入FIN_WAIT_1的终止等待状态。TCP规定FIN报文段即使不携带数据,也要消耗一个序号。
  • 服务端收到客户端发来的请求报文和序列号后,响应给客户端ACK=1确认报文段,服务端的报文序列号,以及ack=u+1。此时服务端进入close_wait状态(关闭等待状态)。此时TCP通知上层应用进程,客户端已经准备关闭了,这时候处于版关闭状态。这时如果向客户端发送数据,客户端仍然需要接收。这个状态需要维持一段时间,如果期间有数据需要发送就进行发送。等待整个CLOSE_WAIT状态持续时间结束。
  • 客户端收到服务端发来的ACK=1确认报文后,进入FIN_WAIT_2的终止等待状态,等待服务端是否还有数据需要进行发送。
  • 服务端发送完最后的数据之后,就向客户端发送连接释放报文,FIN=1,ack=u+1。由于在半关闭状态,服务器可能还会发送一些数据,所以这时的序列号也会随之改变。服务端发送完的报文序列号之后就进入LAST_ACK最后确认状态,等待客户端进行确认。
  • 客户端收到服务端发送的连接释放报文后必须发送确认ACK=1报文,以及自己的序列号给服务端表示已经接收并进入TIME-WAIT(时间等待状态)注意此时客户端并未关闭,而是经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB之后才进入CLOSED状态。
  • 服务端只要接收到客户端的确认连接释放报文,就立即进入CLOSED关闭状态,同样撤销掉了TCB之后就结束了这次的TCP连接。因此可以看出,(除非特殊情况)服务端关闭是要早于客户端的。

golang实现简单的tcp连接建立

服务端

主要分为3部分

  • 建立tcp监听通道,指定监听端口
net.Listen("tcp", "127.0.0.1:4399")  (Listener, error)
  • 对通道进行监听
listen.Accept() (Conn, error)
  • 关闭监听通道
defer listen.Close()

完整代码

注意defer语句一定要写在错误处理之后。如果写在错误之前,一旦发生了错误,该连接就不会被生成,进而执行defer语句的时候无法进行通道关闭。

package main
import (
   "fmt"
   "net"
)
func handle(conn net.Conn) {
   defer conn.Close()
   var info [256]byte
   n, err := conn.Read(info[:])
   if err != nil {
      fmt.Println("conn Read fail ,err = ", err)
      return
   }
   fmt.Println("client send info to server si : ", string(info[:n]))
}
func main() {
   // 1. 建立tcp连接监听通道
   listen, err := net.Listen("tcp", "127.0.0.1:4399")
   if err != nil {
      panic(err)
   }
   // 3. 关闭监听通道
   defer listen.Close()
   fmt.Println("server is Listening")
   for {
      // 2. 进行通道监听
      conn, err := listen.Accept()
      if err != nil {
         panic(err)
      }
      // 启动一个协程去单独处理该连接
      go handle(conn)
   }
}

客户端

客户端和服务端一样,也分为三个部分

  • 对指定通道进行连接
net.Dial("tcp", "127.0.0.1:4399") (Conn, error)
  • 连接成功后发送数据
msg := "Hi, I am a client"
conn.Write([]byte(msg))
  • 发送完成后进行关闭连接
defer conn.Close()

完整代码

在这里我只做了简单的处理,将字符串转化为字符切片通过Write的方式发送给了服务端,并且该过程只进行了一次。如果需要多次持续建立连接并且发送,需要主动开启一个for循环,并且设置循环结束条件。

package main
import "net"
func main() {
   // 1. 建立访问通道
   conn, err := net.Dial("tcp", "127.0.0.1:4399")
   if err != nil {
      panic(err)
   }
   defer conn.Close()
   msg := "Hi, I am a client"
   conn.Write([]byte(msg))
}

以上就是golang实现简单的tcp数据传输的详细内容,更多关于golang tcp数据传输的资料请关注我们其它相关文章!

(0)

相关推荐

  • go语言中的udp协议及TCP通讯实现示例

    目录 udp协议 server端 client端 TCP通讯(基本) 服务端 客户端 TCP通讯并发服务器 服务端 客户端 udp协议 server端 package main import ( "fmt" "net" ) func main() { // 创建监听 socket, err := net.ListenUDP("udp4", &net.UDPAddr{ IP: net.IPv4(0, 0, 0, 0), Port: 8080

  • 在Go中构建并发TCP服务器

    开发一个并发TCP服务器,该服务器仅使用大约65行GO代码生成随机数. TCP和UDP服务器随处可见,通过TCP/IP网络为网络客户端提供服务.在本文中,我将在GO编程语言,返回随机数.对于来自TCP客户端的每个传入连接,TCP服务器将启动一个新的goroutine来处理该请求. 你可以找到这个项目,concTCP.go,在GitHub上. 处理TCP连接 程序的逻辑可以在handleConnection()职能,其实现方式如下: func handleConnection(c net.Conn

  • Go语言net包RPC远程调用三种方式http与json-rpc及tcp

    目录 一.服务端 二.http客户端 三.TCP客户端 四.json客户端 五.运行结果 rpc有多种调用方式,http.json-rpc.tcp 一.服务端 在代码中,启动了三个服务 package main import ( "log" "net" "net/http" "net/rpc" "net/rpc/jsonrpc" "sync" ) //go对RPC的支持,支持三个级别:T

  • Go语言TCP从原理到代码实现详解

    目录 引言 TCP介绍 特点 图解 代码实现 1. 连接 1.1 服务端 1.2 客户端 2. 通信 2.1 服务端 2.2 客户端 3. 回复 3.1 服务端 3.2 客户端 引言 基于net包的小应用 完整代码已经上传到github GitHub-TCP 欢迎star和issue TCP介绍 特点 面向连接的运输层协议.在应用程序在使用TCP协议之前,必须先建立TCP连接.在传送数据完毕后,必须释放已经建立的TCP连接. 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的. TC

  • golang基于websocket通信tcp keepalive研究记录

    目录 为什么有tcp Keepalive? tcp Keepalive是否默认开启? 如何设置tcp keepalive? 在Linux内核设置 golang websocket 客户端默认怎么处理tcp keepalive? golang websocket 服务器默认怎么处理tcp keepalive? 为什么有tcp Keepalive? 服务器和客户端建立tcp连接以后,客户端/服务器如何知道对方是否挂掉了? 这时候TCP协议提出一个办法,当客户端端等待超过一定时间后自动给服务端发送一个

  • golang实现简单的tcp数据传输

    目录 前言 首先介绍什么是Tcp协议 什么是可靠数据传输? TCP的快速重传机制 简单介绍TCP连接的三次握手和四次挥手 三次握手 四次挥手 golang实现简单的tcp连接建立 服务端 完整代码 客户端 完整代码 前言 通过golang实现Tcp的连接与信息传输 本文主要介绍Tcp协议以及如何使用golang来建立一个简单的tcp连接服务,并且实现信息的传输. 首先介绍什么是Tcp协议 Tcp协议是传输层的一个可靠数据传输协议,Tcp协议有以下几个特点: 点对点的发送:一个发送方,一个接收方

  • golang实现简单rpc调用过程解析

    目录 基本概念 RPC通信过程 RPC 具体实现 server端 客户端 基本概念 RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务,该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程,RPC最直接的作用就是微服务. RPC通信过程 RPC的通信过程网上介绍很多,这里就不在单独介绍了,具体过程如下:1.Client以本地调用的方式发起调用:2.Client stub收到调用后负责将被调用的方

  • Golang实现简单http服务器的示例详解

    目录 一.基本描述 二 .具体方法 2.1 连接的建立 2.2 http请求解析 2.3 http请求处理 2.4 http请求响应 三.完整示例 一.基本描述 完成一个http请求的处理和响应,主要有以下几个步骤: 监听端口 建立连接 解析http请求 处理请求 返回http响应 完成上面几个步骤,便能够实现一个简单的http服务器,完成对基本的http请求的处理 二 .具体方法 2.1 连接的建立 go中net包下有提供Listen和Accept两个方法,可以完成连接的建立,可以简单看下示例

  • python实现简单的TCP代理服务器

    本文实例讲述了python实现简单的TCP代理服务器的方法,分享给大家供大家参考. 具体实现代码如下: # -*- coding: utf-8 -*- ''' filename:rtcp.py @desc: 利用python的socket端口转发,用于远程维护 如果连接不到远程,会sleep 36s,最多尝试200(即两小时) @usage: ./rtcp.py stream1 stream2 stream为:l:port或c:host:port l:port表示监听指定的本地端口 c:host

  • Python简单实现TCP包发送十六进制数据的方法

    本文实例讲述了Python简单实现TCP包发送十六进制数据的方法.分享给大家供大家参考,具体如下: 举例: 0x12, 0x34可以直接拼成 "\x12\x34". 客户端代码示例: #-*- encoding: utf-8 -*- import json import socket import sys import binascii reload(sys) sys.setdefaultencoding('utf-8') if __name__=="__main__&quo

  • golang实现简单的udp协议服务端与客户端示例

    本文实例讲述了golang实现简单的udp协议服务端与客户端.分享给大家供大家参考,具体如下: 其实udp没有什么服务端和客户端的概念了,只是一个发一个收而已,只是这样较方便能识别和理解. 服务端: 复制代码 代码如下: package main import (     "fmt"     "net" ) func main() {     // 创建监听     socket, err := net.ListenUDP("udp4", &am

  • nodejs简单实现TCP服务器端和客户端的聊天功能示例

    本文实例讲述了nodejs简单实现TCP服务器端和客户端的聊天功能.分享给大家供大家参考,具体如下: 服务器端 var net = require('net'); var server = net.createServer(); //聚合所有客户端 var sockets = []; //接受新的客户端连接 server.on('connection', function(socket){ console.log('got a new connection'); sockets.push(soc

  • 基于golang的简单分布式延时队列服务的实现

    一.引言 背景 我们在做系统时,很多时候是处理实时的任务,请求来了马上就处理,然后立刻给用户以反馈.但有时也会遇到非实时的任务,比如确定的时间点发布重要公告.或者需要在用户做了一件事情的X分钟/Y小时后,EG: "PM:我们需要在这个用户通话开始10分钟后给予提醒给他们发送奖励" 对其特定动作,比如通知.发券等等.一般我接触到的解决方法中在比较小的服务里都会自己维护一个backend,但是随着这种backend和server增多,这种方法很大程度和本身业务耦合在一起,所以这时需要一个延

  • python实现简单的tcp 文件下载

    什么是下载? 首先客户端会问服务器,有没有一个xxx的文件啊?服务器开始寻找,找到后对客户端说有,然后客户端在本地新建一个文件,客户端从服务器收到一点数据,就写进这个文件中,再收到一点数据,再写入这个文件中,只要把所有的接收到的数据都写入到这个文件中,就完成了下载的操作. 所以下载需要2个部分.服务器的发送方和客户端的接收方. 我们这里不考虑复杂的情况.什么限速啊,验证啊,文件大小......只实现最简单的逻辑. 客户端参考代码 import socket def main(): # 创建soc

  • Golang 实现简单随机负载均衡

    目录 负载均衡简介 随机负载均衡 测试 随机负载均衡 负载均衡简介 从设备角度实现负载均衡: 硬件负载均衡: 由专门的 负载均衡器 服务提供商,在你的服务器和外部网络之间架设 服务商的 负载均衡器.服务商提供设备和方案帮你处理流量的均衡,不过因为比较费钱包国内没什么人用 软件负载均衡: 包括家喻户晓的Nginx,LVS,Tengine(阿里版Nginx).优点就是成本比较低,但需要运维去配置.维护.会踩坑,但国内都在用基本上网找就有解决方案. 随机负载均衡 无论是Nginx,LVS 均衡负载的核

随机推荐