|
25th October 2003, 04:22 PM | #1 |
Senior Member
Professional user
Join Date: Jul 2003
Posts: 899
|
Re: Sockets
Spoke too soon - started happening again after a little while. I ended up looking at the ac3d.tcl code after all - by the way, it's a very clean implementation, with sensible function names and easy-to-follow logic - it's almost self documenting.
I traced the problem down to the socket #'s being grabbed. I was alternating between socket 400 and 412 when I established a connection. However, if I grabbed the same socket twice in a row, AC3D closed it immediately the second time. I found this code in ac3d.tcl: Code:
proc do_connection {sock ip port} { fileevent $sock readable "get_cmd $sock" puts "New socket connected to AC3D (socket id $sock, remote ip:port $ip:$port)" close_current_command_socket set_command_socket $sock } I was able to fix this by editing my copy of ac3d.tcl to pass the new socket number to close_current_command_socket, then changing the logic to only close the old one if it was a different socket. This allows me to grab the same socket twice in a row w/o getting it clipped by close_current_command_socket. fyi, I also tried the sample ac3dshell.tcl --- it seems to work fine, since the ac3dshell.tcl doesn't close the socket when it's done (it lets AC3D do it). In my own app, I allow the socket to be opened and closed. I ended up changing 4 lines of code across three functions. The changes I made in my file are as follows (see comments): Code:
proc do_connection {sock ip port} { fileevent $sock readable "get_cmd $sock" puts "New socket connected to AC3D (socket id $sock, remote ip:port $ip:$port)" # DH - Added $sock parameter close_current_command_socket $sock set_command_socket $sock } Code:
proc disable_socket_commands {} { global listensock if { $listensock != 0 } { # DH - Added 0 parameter close_current_command_socket 0 set err [catch { close $listensock }] set listensock 0 } puts "Command socket connections disabled" } Code:
# DH - Added "sock" argument, which is the currently open socket # (sock == 0 if we want to force a close). # This allows close_current_command_socket to compare the old # socket (the one it's trying to close) against the new socket, # in the event a function like "do_connection" cleans up the # old socket first. proc close_current_command_socket { sock } { global rsock # DH - added "&& $rsock != $sock" if { $rsock != 0 && $rsock != $sock } { set err [catch { close $rsock }] puts "tcl socket $rsock disconnected by AC3D" set rsock 0 } } I'm not sure how often this feature of AC3D gets used, but I'm *really* glad it's there. So far, it's allowing me to write a fairly robust property editor with my own GUI (so I'm not so dependent on TCL, with which I'm not terribly adept). Thanks, Dennis |
|
|