1024programmer Java Implementation method of golangsocket breakpoint resume uploading large files

Implementation method of golangsocket breakpoint resume uploading large files

In daily programming, we will definitely encounter the use of sockets to transfer file content. If it is a large file, it cannot be interrupted for some reason in the middle of the transfer, and the file content can be transferred again. Yes, we need to resume the transmission, that is, continue to send the file content from the last transmission location.

It is actually not difficult to continue the transfer. The idea I understand is roughly as follows:

The client sends a message to ask the server for the location of the file content you last received

The server tells the client the location of the last file content received

The client will continue to send the file content from the last breakpoint

After the client completes sending the file content, it notifies the server and then disconnects

Let’s take a look at the implementation of the code

Server

 // file name: server.go

 package main

 import (
  "os"
  "io"
  "net"
  "log"
  "strconv"
  // "time"
 )

 //Append the received content to the file
 func writeFile(content []byte) {
  if len(content) != 0 {
   fp, err := os.OpenFile("test_1.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0755)
   defer fp.Close()
   if err != nil {
    log.Fatalf("open file faild: %s\n", err)
   }
   _, err = fp.Write(content)
   if err != nil {
    log.Fatalf("append content to file faild: %s\n", err)
   }
   log.Printf("append content: 【%s】 success\n", string(content))
  }
 }

 // Get the size of the received content
 // (Resuming the upload requires notifying the client where to start sending the file content)
 func getFileStat() int64 {
  fileinfo, err := os.Stat("test_1.txt")
  if err != nil {
   // If the test_1.txt file is not created for the first time, return 0 directly.
   // Tell the client to send the file contents from the beginning
   if os.IsNotExist(err) {
    log.Printf("file size: %d\n", 0)
    return int64(0)
   }
   log.Fatalf("get file stat faild: %s\n", err)
  }
  log.Printf("file size: %d\n", fileinfo.Size())
  return fileinfo.Size()
 }

 func serverConn(conn net.Conn) {
  defer conn.Close()
  for {
   var buf = make([]byte, 10)
   n, err := conn.Read(buf)
   if err != nil {
    if err == io.EOF {
     log.Println("server io EOF\n")
     return
    }
    log.Fatalf("server read faild: %s\n", err)
   }
   log.Printf("recevice %d bytes, content is 【%s】\n", n, string(buf[:n]))
   // Determine the message sent by the client
   // If it is 'start-->', it means you need to tell the client where to start reading the file data and sending it.
   switch string(buf[:n]) {
   case "start-->":
    off := getFileStat()
    // int conver string
    stringoff := strconv.FormatInt(off, 10)
    _, err = conn.Write([]byte(stringoff))
    if err != nil {
     log.Fatalf("server write faild: %s\n", err)
    }
    continue
   case "<--end":
    // Exit if receiving a message from the client that all file contents have been sent.
    log.Fatalf("receive over\n")
    return
   //default:
   // time.Sleep(time.Second * 1)
   }
   //Save the content sent by the client to the file
   writeFile(buf[:n])
  }
 }

 func main() {
  // Create a listener
  l, err := net.Listen("tcp", ":8888")
  if err != nil {
   log.Fatalf("error listen: %s\n", err)
  }
  defer l.Close()

  log.Println("waiting accept.")
  //Allow client connections. When there is no client connection, it will always be blocked.
  conn, err := l.Accept()
  if err != nil {
   log.Fatalf("accept faild: %s\n", err)
  }
  serverConn(conn)
 }

Client

 // file name: client.go

 package main

 import (
  "os"
  "io"
  "net"
  "log"
  "time"
  "strconv"
 )

 // Get the message sent by the server
 func clientRead(conn net.Conn) int {
  buf := make([]byte, 5)
  n, err := conn.Read(buf)
  if err != nil {
   log.Fatalf("receive server info faild: %s\n", err)
  }
  // string conver int
  off, err := strconv.Atoi(string(buf[:n]))
  if err != nil {
   log.Fatalf("string conver int faild: %s\n", err)
  }
  return off
 }

 //Send message to server
 func clientWrite(conn net.Conn, data []byte) {
  _, err := conn.Write(data)
  if err != nil {
   log.Fatalf("send [%s] content faild: %s\n", string(data), err)
  }
  log.Printf("send [%s] content success\n", string(data))
 }

 // client conn
 func clientConn(conn net.Conn) {
  defer conn.Close()

  //Send the "start-->" message to notify the server that I want to start sending the file content.
  // Hurry up and tell me how much content you have received, and I will continue sending it from the content you have received.
  clientWrite(conn, []byte("start-->"))
  off := clientRead(conn)

  // send file content
  fp, err := os.OpenFile("test.txt", os.O_RDONLY, 0755)
  if err != nil {
   log.Fatalf("open file faild: %s\n", err)
  }
  defer fp.Close()

  // set file seek
  //Set where to start reading the file content
  _, err = fp.Seek(int64(off), 0)
  if err != nil {
   log.Fatalf("set file seek faild: %s\n", err)
  }
  log.Printf("read file at seek: %d\n", off)

  for {
   //Send 10 bytes of content each time
   data := make([]byte, 10)
   n, err := fp.Read(data)
   if err != nil {
    if err == io.EOF {
     // If the file content has been read
     //Send a '<--end' message to notify the server that the file content has been sent.
     time.Sleep(time.Second * 1)clientWrite(conn, []byte("<--end"))
     log.Println("send all content, now quit")
     break
    }
    log.Fatalf("read file err: %s\n", err)
   }
   //Send the file content to the server
   clientWrite(conn, data[:n])
  }
 }

 func main() {
  // connect timeout 10s
  conn, err := net.DialTimeout("tcp", ":8888", time.Second * 10)
  if err != nil {
   log.Fatalf("client dial faild: %s\n", err)
  }
  clientConn(conn)
  }

The client reads the content of the file test.txt and sends it to the server, and the server saves the received file content in the test_1.txt file. The way we simulate breakpoint resumption is:

Send the content of the test.txt file to the server for the first time

Modify the test.txt file and add some content

Run server socket and client socket again to observe whether the client only sends the newly added file content to the server

 # Assume that my test.txt file has the following content
 $ cat test.txt
 hello golang.

 # Run server socket first and then client socket (run in two terminal windows respectively)
 $ go run server.go
 $ go run client.go

 # The server will output the following content
 2018/04/05 23:37:13 waiting to accept.
 2018/04/05 23:37:15 recevice 8 bytes, content is 【start-->】
 2018/04/05 23:37:15 file size: 0
 2018/04/05 23:37:15 recevice 10 bytes, content is 【hello gola】
 2018/04/05 23:37:15 append content: 【hello gola】 success
 2018/04/05 23:37:15 recevice 2 bytes, content is 【n.】
 2018/04/05 23:37:15 append content: 【n.】 success
 2018/04/05 23:37:16 recevice 6 bytes, content is [】 content success
 2018/04/05 23:37:15 read file at seek: 0
 2018/04/05 23:37:15 send 【hello gola】 content success
 2018/04/05 23:37:15 send 【n.】 content success
 2018/04/05 23:37:16 send [】
 2018/04/05 23:44:34 file size: 12
 2018/04/05 23:44:34 recevice 10 bytes, content is [
 hello pyt】
 2018/04/05 23:44:34 append content: 【
 hello pyt] success
 2018/04/05 23:44:34 recevice 4 bytes, content is 【hon.】
 2018/04/05 23:44:34 append content: 【hon.】 success
 2018/04/05 23:44:35 recevice 6 bytes, content is [ information sent by the client, the server will obtain the location of the last received file content and notify the client (the file size here is 12)

 # The client will output the following content
 2018/04/05 23:44:34 send 【start-->】 content success
 2018/04/05 23:44:34 read file at seek: 12
 2018/04/05 23:44:34 send 【
 hello pyt】 content success
 2018/04/05 23:44:34 send 【hon.】 content success
 2018/04/05 23:44:35 send [<--end] content success
 2018/04/05 23:44:35 send all content, now quit
 # Our client obtains the file location returned by the server, and uses Seek to specify where to start reading the file.
 # From the log, we can see that our client only sent the appended content: hello python. to the server.

 # Let’s see if the content of the test_1.txt file is consistent with test.txt at this time
 $ cat test_1.txt
 hello golang.
 hello python.

The above method for implementing golang socket breakpoint resumable upload of large files is all the content shared by the editor. I hope it can give you a reference, and I hope you will support it.

This article is from the internet and does not represent1024programmerPosition, please indicate the source when reprinting:https://www.1024programmer.com/784274

author: admin

Previous article
Next article

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

Contact us

181-3619-1160

Online consultation: QQ交谈

E-mail: [email protected]

Working hours: Monday to Friday, 9:00-17:30, holidays off

Follow wechat
Scan wechat and follow us

Scan wechat and follow us

Follow Weibo
Back to top
首页
微信
电话
搜索