Strip file and write the chunks concurrently to server through TCP shows broken pipe error

Strip file and write the chunks concurrently to server through TCP shows broken pipe error



My client divides a file into multiple amount of chunks (128mb each), then it will upload the chunks to multiple servers concurrently using goroutines.



However, when I use more than 1 goroutine, I got an error from the my client program.


write tcp [::1]:49324->[::1]:2001: write: broken pipe



And in my server, the error is


EOF



Note that the broken pipe error and EOF error occurs in different chunks. For example, broken pipe error might happen when writing chunk 1 while EOF error might happen when server is receiving chunk 2.



Below is the client code:


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



Below is the server code:


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




Big thanks in advance.





It makes no sense to send things concurrently to a socket. What use is data that's randomly interleaved?
– JimB
Apr 1 '17 at 14:26





You are right, thanks for the reply. Just to confirm, I want to ask: so sending things concurrently to a socket means that data are properly gonna be interleaved. But if I send it using a different socket (same IP+port from server, different IP+port from client) then data will not be interleaved?
– vc25
Apr 1 '17 at 18:14





No, there is no way for the data to somehow cross between connections. Each TCP socket is a separate stream.
– JimB
Apr 1 '17 at 18:21





I see. I was just asking because I want to know what happens when there are concurrent upload from multiple clients. Thanks
– vc25
Apr 1 '17 at 18:52





I just checked that each time the goroutines connect to the server, it uses a new port, which means it is a different socket pair. Shouldn't it mean that data will not be randomly interleaved as they are in separate streams?
– vc25
Apr 2 '17 at 15:39




1 Answer
1



In your client sentByte should be a local variable to the sender goroutine. Since you have declared it as a global, there is a race condition in your code. Try the below fix:


sentByte


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





Thanks, it solves my problem. But I have got another problem now. Although I can upload the files to the server without dropping any bytes, some bytes are incorrect (I checked the bytes using cmp and od). Would you know why?
– vc25
Apr 1 '17 at 13:47






I think that's because of your buffer size check in the client. There might be some edge condition that's maybe sending same bits of data twice.For example, the very last chunk of the file may not have enough bytes to fill up the chunk causing the condition sentByte == CHUNKSIZE to behave badly.
– abhink
Apr 1 '17 at 23:15


sentByte == CHUNKSIZE





Thanks, actually I did check but I just didn't put that in the code snippet above. The loop for sending the chunk will break when there is a read error from reading the file (eg. EOF). So that shouldn't be the problem. The number of bytes of the file I received by downloading and assembling the chunks is the same as the file I uploaded, but the content is not.
– vc25
Apr 3 '17 at 10:35



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

PHP code is not being executed, instead code shows on the page

Ĝň ċũ,İĨĻĐđēĵſ ĤŹĝĽķũ ĆŹđě,ļ łĂģĚ ŻŷĶĸĦķĖĝŔ ūŬĿŜćīŴĽĺ,ľ,ũĽňĎźāœ,ĉŃĩ,ĎĻē,ŕųūČœijčĶŶĻijŕ,ĩěŗſŗāŸņŰž,Žů ĭğŪľ Čŗćļžĵţ Ūĉņ ĵ ůŁ ţŅ,ĮŶ ŁŵĮ śŁĬŇŏ ŮĜʼnœĦā,Ũŏ Ź ŖŀšĦ ŃłĉŹŅťŸŇ,ŷī