2014-09-25 2 views
4

새로운 기능입니다.이 클라이언트/서버 파일 전송 코드를 디버깅하는 데 문제가 있습니다. 서버에서 719kb png 파일을 요청하면 719kb를 얻습니다. 그러나 완벽하지는 않습니다. 파일을 열면 png가 완전히 표시되지 않습니다. (일부는 잘립니다.) 여기서 어디가 잘못 될까요?이동 중에 TCP 클라이언트/서버 파일 전송

// 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 // 

답변

5

당신은 당신이 여분의 쓰레기 바이트를해야합니다 보내 그렇지 않으면 마지막 fileBuffer, ReadAt에서 반환 된 바이트 수를 설명 할 필요가

예 :.

또한 bytes.Trim(fileBuffer, "\x00")
n, err := file.ReadAt(fileBuffer, currentByte) 
connection.Write(fileBuffer[:n]) 

은 일반적으로부터 거의 모든 이진 파일을 파괴 할 것이다 그들은 null 바이트를 사용한다. 공간을 채우기 위해. 또한

이를위한 적절한 방법은

io.Copy를 사용 :

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")