Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go中的TCP客户端/服务器文件传输_Tcp_Go - Fatal编程技术网

Go中的TCP客户端/服务器文件传输

Go中的TCP客户端/服务器文件传输,tcp,go,Tcp,Go,我是新手,调试此客户机/服务器文件传输代码时遇到问题。当我从服务器请求一个719kb的png文件时,我得到了719kb。。但并不完美,当我打开png时,它并没有完全显示出来(有些被切断了。我哪里出了问题 // CLIENT /// package main import ( "bufio" "bytes" "fmt" "io" "log" "net" "os" "strings" ) const BUFFER_SIZE

我是新手,调试此客户机/服务器文件传输代码时遇到问题。当我从服务器请求一个719kb的png文件时,我得到了719kb。。但并不完美,当我打开png时,它并没有完全显示出来(有些被切断了。我哪里出了问题

// CLIENT ///
    package main

import (
    "bufio"
    "bytes"
    "fmt"
    "io"
    "log"
    "net"
    "os"
    "strings"
)

const BUFFER_SIZE = 1024

func main() {

    //get port and ip address to dial

    if len(os.Args) != 3 {
        fmt.Println("useage example: tcpClient 127.0.0.1 7005")
        return
    }

    var ip string = os.Args[1]
    var port string = os.Args[2]

    connection, err := net.Dial("tcp", ip+":"+port)
    if err != nil {
        fmt.Println("There was an error making a connection")
    }

    //read from
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Please enter 'get <filename>' or 'send <filename>' to transfer files to the server\n\n")
    inputFromUser, _ := reader.ReadString('\n')
    arrayOfCommands := strings.Split(inputFromUser, " ")

    if arrayOfCommands[0] == "get" {
        getFileFromServer(arrayOfCommands[1], connection)

    } else if arrayOfCommands[0] == "send" {
        sendFileToServer(arrayOfCommands[1], connection)
    } else {
        fmt.Println("Bad Command")
    }

}

func sendFileToServer(fileName string, connection net.Conn) {

    var currentByte int64 = 0
    fmt.Println("send to client")
    fileBuffer := make([]byte, BUFFER_SIZE)

    var err error

    //file to read
    file, err := os.Open(strings.TrimSpace(fileName)) // For read access.
    if err != nil {
        connection.Write([]byte("-1"))
        log.Fatal(err)
    }
    connection.Write([]byte("send " + fileName))
    //read file until there is an error
    for err == nil || err != io.EOF {

        _, err = file.ReadAt(fileBuffer, currentByte)
        currentByte += BUFFER_SIZE
        fmt.Println(fileBuffer)
        connection.Write(fileBuffer)
    }

    file.Close()
    connection.Close()

}

func getFileFromServer(fileName string, connection net.Conn) {

    var currentByte int64 = 0

    fileBuffer := make([]byte, BUFFER_SIZE)

    var err error
    file, err := os.Create(strings.TrimSpace(fileName))
    if err != nil {
        log.Fatal(err)
    }
    connection.Write([]byte("get " + fileName))
    for {

        connection.Read(fileBuffer)
        cleanedFileBuffer := bytes.Trim(fileBuffer, "\x00")

        _, err = file.WriteAt(cleanedFileBuffer, currentByte)

        currentByte += BUFFER_SIZE

        if err == io.EOF {
            break
        }

    }

    file.Close()
    return

}

// END CLIENT //
// SERVER //
    package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "net"
    "os"
    "strings"
)

const BUFFER_SIZE = 1024
const PORT = "7005"

func main() {

    fmt.Println("start listening")

    server, error := net.Listen("tcp", "localhost:"+PORT)
    if error != nil {
        fmt.Println("There was an error starting the server" + error.Error())
        return
    }

    //infinate loop
    for {

        connection, error := server.Accept()
        if error != nil {
            fmt.Println("There was am error with the connection" + error.Error())
            return
        }
        fmt.Println("connected")
        //handle the connection, on it's own thread, per connection
        go connectionHandler(connection)
    }
}

func connectionHandler(connection net.Conn) {
    buffer := make([]byte, BUFFER_SIZE)

    _, error := connection.Read(buffer)
    if error != nil {
        fmt.Println("There is an error reading from connection", error.Error())
        return
    }
    fmt.Println("command recieved: " + string(buffer))

    //loop until disconntect

    cleanedBuffer := bytes.Trim(buffer, "\x00")
    cleanedInputCommandString := strings.TrimSpace(string(cleanedBuffer))
    arrayOfCommands := strings.Split(cleanedInputCommandString, " ")

    fmt.Println(arrayOfCommands[0])
    if arrayOfCommands[0] == "get" {
        sendFileToClient(arrayOfCommands[1], connection)
    } else if arrayOfCommands[0] == "send" {
        fmt.Println("getting a file")

        getFileFromClient(arrayOfCommands[1], connection)

    } else {
        _, error = connection.Write([]byte("bad command"))
    }

}

func sendFileToClient(fileName string, connection net.Conn) {
    var currentByte int64 = 0
    fmt.Println("send to client")
    fileBuffer := make([]byte, BUFFER_SIZE)

    //file to read
    file, err := os.Open(strings.TrimSpace(fileName)) // For read access.
    if err != nil {

        log.Fatal(err)
    }
    var err2 error

    //read file until there is an error
    for {

        _, err2 = file.ReadAt(fileBuffer, currentByte)
        currentByte += BUFFER_SIZE
        fmt.Println(fileBuffer)
        connection.Write(fileBuffer)

        if err2 == io.EOF {
            break
        }
    }

    file.Close()
    return

}

func getFileFromClient(fileName string, connection net.Conn) {

    var currentByte int64 = 0

    fileBuffer := make([]byte, BUFFER_SIZE)

    var err error
    file, err := os.Create(strings.TrimSpace(fileName))
    if err != nil {
        log.Fatal(err)
    }
    connection.Write([]byte("get " + fileName))
    for err == nil || err != io.EOF {

        connection.Read(fileBuffer)

        cleanedFileBuffer := bytes.Trim(fileBuffer, "\x00")

        _, err = file.WriteAt(cleanedFileBuffer, currentByte)
        if len(string(fileBuffer)) != len(string(cleanedFileBuffer)) {
            break
        }
        currentByte += BUFFER_SIZE

    }

    connection.Close()
    file.Close()
    return

}

// END SERVER //
//客户端///
包干管
进口(
“布菲奥”
“字节”
“fmt”
“io”
“日志”
“净额”
“操作系统”
“字符串”
)
常量缓冲区大小=1024
func main(){
//获取要拨号的端口和ip地址
如果len(os.Args)!=3{
fmt.Println(“使用示例:tcpClient 127.0.0.1 7005”)
返回
}
var ip string=os.Args[1]
var port string=os.Args[2]
连接,错误:=网络拨号(“tcp”,ip+:“+端口)
如果错误!=零{
fmt.Println(“建立连接时出错”)
}
//阅读
reader:=bufio.NewReader(os.Stdin)
fmt.Print(“请输入'get'或'send'将文件传输到服务器\n\n”)
inputFromUser,\:=reader.ReadString('\n')
arrayOfCommands:=strings.Split(inputFromUser,“”)
如果ArrayOfCommand[0]=“获取”{
getFileFromServer(ArrayOfCommand[1],连接)
}如果ArrayOfCommand[0]=“发送”,则为else{
sendFileToServer(ArrayOfCommand[1],连接)
}否则{
fmt.Println(“错误命令”)
}
}
func sendFileToServer(文件名字符串,连接网络.Conn){
var currentByte int64=0
fmt.Println(“发送给客户”)
fileBuffer:=生成([]字节,缓冲区大小)
变量错误
//要读取的文件
文件,err:=os.Open(strings.TrimSpace(fileName))//用于读取访问。
如果错误!=零{
连接.写入([]字节(“-1”))
log.Fatal(错误)
}
connection.Write([]字节(“发送”+文件名))
//读取文件直到出现错误
对于err==nil | | err!=io.EOF{
_,err=file.ReadAt(文件缓冲区,当前字节)
currentByte+=缓冲区大小
fmt.Println(文件缓冲区)
connection.Write(文件缓冲区)
}
file.Close()文件
连接。关闭()
}
func getFileFromServer(文件名字符串,连接网络.Conn){
var currentByte int64=0
fileBuffer:=生成([]字节,缓冲区大小)
变量错误
文件,err:=os.Create(strings.TrimSpace(文件名))
如果错误!=零{
log.Fatal(错误)
}
connection.Write([]字节(“get”+文件名))
为了{
connection.Read(文件缓冲区)
cleanedFileBuffer:=bytes.Trim(fileBuffer,“\x00”)
_,err=file.WriteAt(cleanedFileBuffer,currentByte)
currentByte+=缓冲区大小
如果err==io.EOF{
打破
}
}
file.Close()文件
返回
}
//终端客户端//
//服务器//
包干管
进口(
“字节”
“fmt”
“io”
“日志”
“净额”
“操作系统”
“字符串”
)
常量缓冲区大小=1024
const PORT=“7005”
func main(){
fmt.Println(“开始监听”)
服务器,错误:=net.Listen(“tcp”,“localhost:+端口”)
如果错误!=nil{
fmt.Println(“启动服务器时出错”+error.error())
返回
}
//内环
为了{
连接,错误:=server.Accept()
如果错误!=nil{
fmt.Println(“连接有一个错误”+error.error())
返回
}
fmt.Println(“已连接”)
//在每个连接的自身线程上处理连接
go connectionHandler(连接)
}
}
func connectionHandler(连接net.Conn){
缓冲区:=生成([]字节,缓冲区大小)
_,错误:=连接。读取(缓冲区)
如果错误!=nil{
fmt.Println(“读取连接时出错”,error.error())
返回
}
fmt.Println(“接收到的命令:“+字符串(缓冲区))
//循环直到断开
cleanedBuffer:=字节数.Trim(缓冲区“\x00”)
cleanedInputCommandString:=strings.TrimSpace(string(cleanedBuffer))
ArrayOfCommand:=strings.Split(cleanedInputCommandString,“”)
fmt.Println(数组命令[0])
如果ArrayOfCommand[0]=“获取”{
sendFileToClient(ArrayOfCommand[1],连接)
}如果ArrayOfCommand[0]=“发送”,则为else{
fmt.Println(“获取文件”)
getFileFromClient(ArrayOfCommand[1],连接)
}否则{
_,error=connection.Write([]字节(“错误命令”))
}
}
func sendFileToClient(文件名字符串,连接网络.Conn){
var currentByte int64=0
fmt.Println(“发送给客户”)
fileBuffer:=生成([]字节,缓冲区大小)
//要读取的文件
文件,err:=os.Open(strings.TrimSpace(fileName))//用于读取访问。
如果错误!=零{
log.Fatal(错误)
}
var err2错误
//读取文件直到出现错误
为了{
_,err2=file.ReadAt(文件缓冲区,当前字节)
currentByte+=缓冲区大小
fmt.Println(文件缓冲区)
connection.Write(文件缓冲区)
如果err2==io.EOF{
打破
}
}
file.Close()文件
返回
}
func getFileFromClient(文件名字符串,连接网络.Conn){
var currentByte int64=0
fileBuffer:=生成([]字节,缓冲区大小)
变量错误
文件,err:=os.Create(strings.TrimSpace(文件名))
如果错误!=零{
log.Fatal(错误)
}
connection.Write([]字节(“get”+文件名))
对于err==nil | | err!=io.EOF{
connection.Read(文件缓冲区)
cleanedFileBuffer:=bytes.Trim(fileBuffer,“\x00”)
_,err=file.WriteAt(cleanedFileBuffer,currentByte)
如果len(string(fileBuffer))!=len(string(cleanedFileBuffer)){
打破
}
currentByte+=缓冲区大小
}
连接。关闭()
file.Close()文件
返回
}
//终端服务器//

您需要说明从
ReadAt
返回的字节数,否则您发送的最后一个文件缓冲区将有额外的垃圾字节

例如:

n, err := file.ReadAt(fileBuffer, currentByte)
connection.Write(fileBuffer[:n])
而且
bytes.Trim(fileBuffer,“\x00”)
会破坏几乎所有的二进制文件,因为它们通常使用空字节来填充空间

这样做的正确方法是
file, err := os.Open(strings.TrimSpace(fileName)) // For read access.
if err != nil {
    log.Fatal(err)
}
defer file.Close() // make sure to close the file even if we panic.
n, err = io.Copy(connection, file)
if err != nil {
    log.Fatal(err)
}
fmt.Println(n, "bytes sent")