我的客户端将文件分成多个块(每个128mb),然后使用goroutine将块同时上传到多个服务器。
然而,当我使用超过1个goroutine时,我的客户端程序出错了。
write tcp [::1]:49324->[::1]:2001: write: broken pipe
在我的服务器中,错误是
EOF
请注意,损坏的管道错误和EOF错误发生在不同的块中。例如,写入块1时可能会发生损坏的管道错误,而当服务器收到块2时可能会发生EOF错误。
以下是客户端代码:
//set maximum no. of goroutine running in the back
maxGoroutines := 3
guard := make(chan struct{}, maxGoroutines)
var sentByte int64
for i:= 0; i < chunkCount; i += 1{
guard <- struct{}{}
go func(i int){
index := i%len(serverList)
vsConnection, _ := net.Dial("tcp", serverList[index])
sentByte=0
file, _ := os.Open(fileName)
file.Seek(int64(i)*CHUNKSIZE,0) //CHUNKSIZE is 134217728
for {
n, _ := file.Read(sendBuffer)
n2, err2 := vsConnection.Write(sendBuffer[:n])
if err2 != nil {
fmt.Println("err2",err2,chunkName)
}
if(n2!=65536){ //65536 is size of sendBuffer
fmt.Println("n2",n2)
}
sentByte = sentByte+int64(n)
if(sentByte == CHUNKSIZE){
break;
}
}
vsConnection.Close()
file.Close()
<-guard
}(i)
}
以下是服务器代码:
func main() {
mapping := cmap.New()
server, error := net.Listen("tcp", ":2001")
if error != nil {
fmt.Println("There was an error starting the server" + error.Error())
return
}
for {
connection, error := server.Accept()
if error != nil {
fmt.Println("There was am error with the connection" + error.Error())
return
}
//one goroutine per connection
go ConnectionHandler(connection,mapping)
}
}
func ConnectionHandler(connection net.Conn, mapping cmap.ConcurrentMap) {
fmt.Println("Connected")
//make a buffer to hold data
var bufferFile bytes.Buffer
writer := bufio.NewWriter(&bufferFile)
var receivedBytes int64
receivedBytes=0
for {
if(CHUNKSIZE<=receivedBytes){
break
}
n,err := io.CopyN(writer, connection, BUFFERSIZE)
receivedBytes += n
if err != nil {
fmt.Println("err", err.Error(), fileName)
break
}
}
mapping.Set(fileName,bufferFile.Bytes())
connection.Close()
}
提前非常感谢。
答案 0 :(得分:3)
在您的客户端sentByte
应该是发件人goroutine的本地变量。由于您已将其声明为全局,因此代码中存在竞争条件。尝试以下修复:
go func(i int){
index := i%len(serverList)
vsConnection, _ := net.Dial("tcp", serverList[index])
sentByte := 0 // make sentByte a local variable, so each goroutine
// has its own copy
file, _ := os.Open(fileName)
file.Seek(int64(i)*CHUNKSIZE,0) //CHUNKSIZE is 134217728
for {
n, _ := file.Read(sendBuffer)
// ...