golang 使用tcp发送多个文件

我有这样一个需求,有A,B两台服务器,A服务器会不停的往B服务器发送大量大小不固定的文件。为防止并发过高将服务器端口占完,所有采用tcp长连接。A服务器通过tcp连接B服务器,然后不停的往B服务器发送大量文件。

现在出现了这么个问题,我同时发送大量文件的时候所有的文件被写入进了1个文件当中。

代码如下:

发送端:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net"
)

func main() {
    conn, err := net.Dial("tcp", ":9900")
    if err != nil {
        log.Printf("%+v\n", err)
        return
    }
    var num = 1
    for {
        if num > 2 {
            break
        }
        fname := fmt.Sprintf("./file/%d.jpg", 7)
        b, err := ioutil.ReadFile(fname)
        if err != nil {
            log.Printf("%+v\n", err)
            return
        }
        conn.Write(b)

        num += 1
    }

}

接收端:

package main

import (
    "fmt"
    "log"
    "net"
    "os"
    "sync"
)

func main() {
    listen, err := net.Listen("tcp", ":9900")
    if err != nil {
        log.Printf("%+v\n", err)
        return
    }

    for {
        conn, err := listen.Accept()
        if err != nil {
            log.Printf("%+v\n", err)
            return
        }
        go handler(conn)
    }

}
func handler(conn net.Conn) {
    defer conn.Close()
    for {
        var buffer = make([]byte, 1024)
        n, err := conn.Read(buffer)
        if err != nil {
            log.Printf("%+v\n", err)
            return
        }
        if n > 0 {
            fname := fmt.Sprintf("./tmp/%d.jpg", fname())
            f, err := os.OpenFile(fname, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0777)
            if err != nil {
                log.Printf("%+v\n", err)
                return
            }
            f.Write(buffer[:n])

            log.Println("n:", n)
            for {
                var buf = make([]byte, 1024)
                n, err := conn.Read(buf)
                if err != nil {
                    log.Printf("%+v\n", err)
                    return
                }
                log.Println("n:", n)
                f.Write(buf[:n])
                if n != (1024) {
                    log.Println(fname, "写入完成")
                    f.Close()
                    break
                }
            }
        }
    }
}

var fn = 1

func fname() int {
    wd := sync.Mutex{}
    wd.Lock()
    n := fn + 1
    wd.Unlock()
    return n
}
阅读 4.4k
1 个回答

这跟语言无关,而是传输协议的特性,TCP 是传输层协议,并且是流式传输,接收端不并知道里面的数据是什么,也不知道什么时候结束,只会无差别接收,直到客户端说发完了(FIN)。所以你应该在应用层来区分数据是一个文件、多个文件或者是其它一些东西。

比如,你可以使用标准的 HTTP 协议,因为它能标识一段数据在哪里结束。

又或者,使用自己定的协议,如数据的前 8 个字节标识此段数据有多长,你就可以先读 8 个字节,发现里面说此段有 n 个字节,你就再读 n 个字节;下个循环依旧

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题