From: Hrachya.Aghajanyan on
On Jan 7, 8:52 pm, "Gerald W. Lester" <Gerald.Les...(a)cox.net> wrote:
> Hrachya.Aghajan...(a)gmail.com wrote:
> > On Jan 7, 10:18 am, "Hrachya.Aghajan...(a)gmail.com"
> > <hrachya.aghajan...(a)gmail.com> wrote:
> >> Hi,
>
> >> I wrote a simple send-receive mechanism for binary .tar.gz files over
> >> socket.  Client on Unix sends the file and the server on Windows
> >> receives the file .  When I run it, somehow the received file is much
> >> smaller than the original file sent from the client.
>
> >> Could you please see my code below and tell me if there's special
> >> handling necessary for .tar.gz files  ?  Thank you!
>
> >>       .........
> >>       ...........
> >>     # Connects to the server
> >>     if { [catch  {set s [socket 10.10.0.165 2112]} err]} {
> >>         puts "ERROR: Failed to connect to the server (10.10.0.165):
> >> $err"
> >>         return
> >>     }
>
> >>     # Control the way file I/O is done using channel
> >>     fconfigure $s -buffering line
>
> >>     puts $s $p_layer
> >>     puts $s $t_figure
> >>    .....
> >>    .....
> >>    ################################################
> >>     # Sending binary layers.tar.gz from client
> >>     ################################################
> >>     set size [file size layers.tar.gz]
> >>     set in0 [open layers.tar.gz]
> >>     fconfigure $in0 -translation binary -buffersize 50000
>
> >>     fconfigure $s -translation binary -buffersize 50000
> >>     puts $s [list layers.tar.gz $size]
> >>     fcopy $in0 $s -size $size
> >>     flush $s
> >>     close $in0
>
> >>     # Wait for the complete file transfer
> >>     after 10000
>
> >>     close $s
>
> >> }
>
> >>     ############################################
> >>     # Receiving layers.tar.gz on server
> >>     ############################################
> >>     fconfigure $sock -translation binary -buffersize 50000
> >>     gets $sock line
> >>     foreach {name size} $line {}
> >>     puts "$sock $port: Getting layer files from client"
>
> >>     set out0 [open $elib0/layers.tar.gz w]
>
> >>     fconfigure $out0 -translation binary -buffersize 50000
> >>     fcopy $sock $out0 -size $size
> >>     close $out0
> >>     delay
> >>     close $sock
>
> >> }
>
> > I guess I found the error :) The doc says "When reading binary
> > information from a channel only read should be used."
>
> Also, you should do the puts of the size before reconfiguring the channel as
> binary -- or better yet change your protocol to something where the first
> record has a header of a known length and that record contains the file name
> and size.  Then switch to copy mode.
>
> --
> +------------------------------------------------------------------------+
> | Gerald W. Lester                                                       |
> |"The man who fights for his ideals is the man who is alive." - Cervantes|
> +------------------------------------------------------------------------+

Hi Gerald,

Do you mean I should use the line below before reconfiguring the
channel as binary?

puts $s [list layers.tar.gz $size]

and then ..

fconfigure $in0 -translation binary
fconfigure $s -translation binary

Please advise.

Thank you!
H.
From: Hrachya.Aghajanyan on
On Jan 7, 8:52 pm, "Gerald W. Lester" <Gerald.Les...(a)cox.net> wrote:
> Hrachya.Aghajan...(a)gmail.com wrote:
> > On Jan 7, 10:18 am, "Hrachya.Aghajan...(a)gmail.com"
> > <hrachya.aghajan...(a)gmail.com> wrote:
> >> Hi,
>
> >> I wrote a simple send-receive mechanism for binary .tar.gz files over
> >> socket.  Client on Unix sends the file and the server on Windows
> >> receives the file .  When I run it, somehow the received file is much
> >> smaller than the original file sent from the client.
>
> >> Could you please see my code below and tell me if there's special
> >> handling necessary for .tar.gz files  ?  Thank you!
>
> >>       .........
> >>       ...........
> >>     # Connects to the server
> >>     if { [catch  {set s [socket 10.10.0.165 2112]} err]} {
> >>         puts "ERROR: Failed to connect to the server (10.10.0.165):
> >> $err"
> >>         return
> >>     }
>
> >>     # Control the way file I/O is done using channel
> >>     fconfigure $s -buffering line
>
> >>     puts $s $p_layer
> >>     puts $s $t_figure
> >>    .....
> >>    .....
> >>    ################################################
> >>     # Sending binary layers.tar.gz from client
> >>     ################################################
> >>     set size [file size layers.tar.gz]
> >>     set in0 [open layers.tar.gz]
> >>     fconfigure $in0 -translation binary -buffersize 50000
>
> >>     fconfigure $s -translation binary -buffersize 50000
> >>     puts $s [list layers.tar.gz $size]
> >>     fcopy $in0 $s -size $size
> >>     flush $s
> >>     close $in0
>
> >>     # Wait for the complete file transfer
> >>     after 10000
>
> >>     close $s
>
> >> }
>
> >>     ############################################
> >>     # Receiving layers.tar.gz on server
> >>     ############################################
> >>     fconfigure $sock -translation binary -buffersize 50000
> >>     gets $sock line
> >>     foreach {name size} $line {}
> >>     puts "$sock $port: Getting layer files from client"
>
> >>     set out0 [open $elib0/layers.tar.gz w]
>
> >>     fconfigure $out0 -translation binary -buffersize 50000
> >>     fcopy $sock $out0 -size $size
> >>     close $out0
> >>     delay
> >>     close $sock
>
> >> }
>
> > I guess I found the error :) The doc says "When reading binary
> > information from a channel only read should be used."
>
> Also, you should do the puts of the size before reconfiguring the channel as
> binary -- or better yet change your protocol to something where the first
> record has a header of a known length and that record contains the file name
> and size.  Then switch to copy mode.
>
> --
> +------------------------------------------------------------------------+
> | Gerald W. Lester                                                       |
> |"The man who fights for his ideals is the man who is alive." - Cervantes|
> +------------------------------------------------------------------------+

You mean to have a header of a known length like this ?
set f [open $filename]
set data [read $f 1024]

Am I getting you wrong?

Please advise.

Thanks!
H.
From: Gerald W. Lester on
Hrachya.Aghajanyan(a)gmail.com wrote:
> On Jan 7, 8:52 pm, "Gerald W. Lester" <Gerald.Les...(a)cox.net> wrote:
>> Hrachya.Aghajan...(a)gmail.com wrote:
>>> On Jan 7, 10:18 am, "Hrachya.Aghajan...(a)gmail.com"
>>> <hrachya.aghajan...(a)gmail.com> wrote:
>>>> Hi,
>>>> I wrote a simple send-receive mechanism for binary .tar.gz files over
>>>> socket. Client on Unix sends the file and the server on Windows
>>>> receives the file . When I run it, somehow the received file is much
>>>> smaller than the original file sent from the client.
>>>> Could you please see my code below and tell me if there's special
>>>> handling necessary for .tar.gz files ? Thank you!
>>>> .........
>>>> ...........
>>>> # Connects to the server
>>>> if { [catch {set s [socket 10.10.0.165 2112]} err]} {
>>>> puts "ERROR: Failed to connect to the server (10.10.0.165):
>>>> $err"
>>>> return
>>>> }
>>>> # Control the way file I/O is done using channel
>>>> fconfigure $s -buffering line
>>>> puts $s $p_layer
>>>> puts $s $t_figure
>>>> .....
>>>> .....
>>>> ################################################
>>>> # Sending binary layers.tar.gz from client
>>>> ################################################
>>>> set size [file size layers.tar.gz]
>>>> set in0 [open layers.tar.gz]
>>>> fconfigure $in0 -translation binary -buffersize 50000
>>>> fconfigure $s -translation binary -buffersize 50000
>>>> puts $s [list layers.tar.gz $size]
>>>> fcopy $in0 $s -size $size
>>>> flush $s
>>>> close $in0
>>>> # Wait for the complete file transfer
>>>> after 10000
>>>> close $s
>>>> }
>>>> ############################################
>>>> # Receiving layers.tar.gz on server
>>>> ############################################
>>>> fconfigure $sock -translation binary -buffersize 50000
>>>> gets $sock line
>>>> foreach {name size} $line {}
>>>> puts "$sock $port: Getting layer files from client"
>>>> set out0 [open $elib0/layers.tar.gz w]
>>>> fconfigure $out0 -translation binary -buffersize 50000
>>>> fcopy $sock $out0 -size $size
>>>> close $out0
>>>> delay
>>>> close $sock
>>>> }
>>> I guess I found the error :) The doc says "When reading binary
>>> information from a channel only read should be used."
>> Also, you should do the puts of the size before reconfiguring the channel as
>> binary -- or better yet change your protocol to something where the first
>> record has a header of a known length and that record contains the file name
>> and size. Then switch to copy mode.
>>
>> --
>> +------------------------------------------------------------------------+
>> | Gerald W. Lester |
>> |"The man who fights for his ideals is the man who is alive." - Cervantes|
>> +------------------------------------------------------------------------+
>
> Hi Gerald,
>
> Do you mean I should use the line below before reconfiguring the
> channel as binary?
>
> puts $s [list layers.tar.gz $size]
>
> and then ..
>
> fconfigure $in0 -translation binary
> fconfigure $s -translation binary
>
> Please advise.

Yes.

--
+------------------------------------------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
From: Gerald W. Lester on
Hrachya.Aghajanyan(a)gmail.com wrote:
> On Jan 7, 8:52 pm, "Gerald W. Lester" <Gerald.Les...(a)cox.net> wrote:
>> Hrachya.Aghajan...(a)gmail.com wrote:
>>> On Jan 7, 10:18 am, "Hrachya.Aghajan...(a)gmail.com"
>>> <hrachya.aghajan...(a)gmail.com> wrote:
>>>> Hi,
>>>> I wrote a simple send-receive mechanism for binary .tar.gz files over
>>>> socket. Client on Unix sends the file and the server on Windows
>>>> receives the file . When I run it, somehow the received file is much
>>>> smaller than the original file sent from the client.
>>>> Could you please see my code below and tell me if there's special
>>>> handling necessary for .tar.gz files ? Thank you!
>>>> .........
>>>> ...........
>>>> # Connects to the server
>>>> if { [catch {set s [socket 10.10.0.165 2112]} err]} {
>>>> puts "ERROR: Failed to connect to the server (10.10.0.165):
>>>> $err"
>>>> return
>>>> }
>>>> # Control the way file I/O is done using channel
>>>> fconfigure $s -buffering line
>>>> puts $s $p_layer
>>>> puts $s $t_figure
>>>> .....
>>>> .....
>>>> ################################################
>>>> # Sending binary layers.tar.gz from client
>>>> ################################################
>>>> set size [file size layers.tar.gz]
>>>> set in0 [open layers.tar.gz]
>>>> fconfigure $in0 -translation binary -buffersize 50000
>>>> fconfigure $s -translation binary -buffersize 50000
>>>> puts $s [list layers.tar.gz $size]
>>>> fcopy $in0 $s -size $size
>>>> flush $s
>>>> close $in0
>>>> # Wait for the complete file transfer
>>>> after 10000
>>>> close $s
>>>> }
>>>> ############################################
>>>> # Receiving layers.tar.gz on server
>>>> ############################################
>>>> fconfigure $sock -translation binary -buffersize 50000
>>>> gets $sock line
>>>> foreach {name size} $line {}
>>>> puts "$sock $port: Getting layer files from client"
>>>> set out0 [open $elib0/layers.tar.gz w]
>>>> fconfigure $out0 -translation binary -buffersize 50000
>>>> fcopy $sock $out0 -size $size
>>>> close $out0
>>>> delay
>>>> close $sock
>>>> }
>>> I guess I found the error :) The doc says "When reading binary
>>> information from a channel only read should be used."
>> Also, you should do the puts of the size before reconfiguring the channel as
>> binary -- or better yet change your protocol to something where the first
>> record has a header of a known length and that record contains the file name
>> and size. Then switch to copy mode.
>>
>> --
>> +------------------------------------------------------------------------+
>> | Gerald W. Lester |
>> |"The man who fights for his ideals is the man who is alive." - Cervantes|
>> +------------------------------------------------------------------------+
>
> You mean to have a header of a known length like this ?
> set f [open $filename]
> set data [read $f 1024]
>
> Am I getting you wrong?
>
> Please advise.

Nope, that is one way to do it.

Another would be as follows (sending end):
set headerData [list layers.tar.gz $size]
puts -nonewline $s [format {%20.20d} [string length $headerData]]
puts -nonewline $s $headerData
....


On the receiver side:
scan [read $sock 20] %d headerLength
set headerData [read $sock $headerLength]
set fileName [lindex $headerData 0]
set fileSize [lindex $headerData 1]


--
+------------------------------------------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
From: Hrachya.Aghajanyan on
On Jan 9, 11:51 am, "Gerald W. Lester" <Gerald.Les...(a)cox.net> wrote:
> Hrachya.Aghajan...(a)gmail.com wrote:
> > On Jan 7, 8:52 pm, "Gerald W. Lester" <Gerald.Les...(a)cox.net> wrote:
> >> Hrachya.Aghajan...(a)gmail.com wrote:
> >>> On Jan 7, 10:18 am, "Hrachya.Aghajan...(a)gmail.com"
> >>> <hrachya.aghajan...(a)gmail.com> wrote:
> >>>> Hi,
> >>>> I wrote a simple send-receive mechanism for binary .tar.gz files over
> >>>> socket.  Client on Unix sends the file and the server on Windows
> >>>> receives the file .  When I run it, somehow the received file is much
> >>>> smaller than the original file sent from the client.
> >>>> Could you please see my code below and tell me if there's special
> >>>> handling necessary for .tar.gz files  ?  Thank you!
> >>>>       .........
> >>>>       ...........
> >>>>     # Connects to the server
> >>>>     if { [catch  {set s [socket 10.10.0.165 2112]} err]} {
> >>>>         puts "ERROR: Failed to connect to the server (10.10.0.165):
> >>>> $err"
> >>>>         return
> >>>>     }
> >>>>     # Control the way file I/O is done using channel
> >>>>     fconfigure $s -buffering line
> >>>>     puts $s $p_layer
> >>>>     puts $s $t_figure
> >>>>    .....
> >>>>    .....
> >>>>    ################################################
> >>>>     # Sending binary layers.tar.gz from client
> >>>>     ################################################
> >>>>     set size [file size layers.tar.gz]
> >>>>     set in0 [open layers.tar.gz]
> >>>>     fconfigure $in0 -translation binary -buffersize 50000
> >>>>     fconfigure $s -translation binary -buffersize 50000
> >>>>     puts $s [list layers.tar.gz $size]
> >>>>     fcopy $in0 $s -size $size
> >>>>     flush $s
> >>>>     close $in0
> >>>>     # Wait for the complete file transfer
> >>>>     after 10000
> >>>>     close $s
> >>>> }
> >>>>     ############################################
> >>>>     # Receiving layers.tar.gz on server
> >>>>     ############################################
> >>>>     fconfigure $sock -translation binary -buffersize 50000
> >>>>     gets $sock line
> >>>>     foreach {name size} $line {}
> >>>>     puts "$sock $port: Getting layer files from client"
> >>>>     set out0 [open $elib0/layers.tar.gz w]
> >>>>     fconfigure $out0 -translation binary -buffersize 50000
> >>>>     fcopy $sock $out0 -size $size
> >>>>     close $out0
> >>>>     delay
> >>>>     close $sock
> >>>> }
> >>> I guess I found the error :) The doc says "When reading binary
> >>> information from a channel only read should be used."
> >> Also, you should do the puts of the size before reconfiguring the channel as
> >> binary -- or better yet change your protocol to something where the first
> >> record has a header of a known length and that record contains the file name
> >> and size.  Then switch to copy mode.
>
> >> --
> >> +------------------------------------------------------------------------+
> >> | Gerald W. Lester                                                       |
> >> |"The man who fights for his ideals is the man who is alive." - Cervantes|
> >> +------------------------------------------------------------------------+
>
> > You mean to have a header of a known length like this ?
> > set f [open $filename]
> > set data [read $f 1024]
>
> > Am I getting you wrong?
>
> > Please advise.
>
> Nope, that is one way to do it.
>
> Another would be as follows (sending end):
> set headerData [list layers.tar.gz $size]
> puts -nonewline $s [format {%20.20d} [string length $headerData]]
> puts -nonewline $s $headerData
> ...
>
> On the receiver side:
> scan [read $sock 20] %d headerLength
> set headerData [read $sock $headerLength]
> set fileName [lindex $headerData 0]
> set fileSize [lindex $headerData 1]
>
> --
> +------------------------------------------------------------------------+
> | Gerald W. Lester                                                       |
> |"The man who fights for his ideals is the man who is alive." - Cervantes|
> +------------------------------------------------------------------------+

Thanks for the pointers, Gerald! That helped a lot.

I simplified the code a bit and now can get the file on the server in
the original size.

################ Server ########################
proc receive_file { dir sock addr port } {
gets $sock gzip_file
gets $sock datasize
puts "Receiving file: $gzip_file($datasize)"
fconfigure $sock -translation binary -buffering none

set fid [open "$dir/layout.tar.gz" w]
fconfigure $fid -translation binary -buffering none -eofchar ""

while {[gets $sock line] >= 0} {
puts $fid "$line"
}
flush $fid
close $fid
fconfigure $sock -translation auto -buffering line
}


########### Client ###########################
proc send_file { dir gzip_file sock } {
puts "\INFO: Sending file $gzip_file"
puts $sock "$filename"
puts $sock "[file size "$dir/$gzip_file"]"
fconfigure $sock -translation binary -buffering none

set fid [open "$dir/$gzip_file" r]
fconfigure $fid -translation binary -buffering none -eofchar ""

while {[eof $fid] == 0 } {
gets $fid line
puts -nonewline $sock "$line"

}
flush $sock
close $fid
fconfigure $sock -translation auto -buffering line
}

Thanks!
-H.