This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

check if socket closed by remote

Old posts that have not been replied to for several years.
Locked
User avatar
De Kus
Revered One
Posts: 1361
Joined: Sun Dec 15, 2002 11:41 am
Location: Germany

check if socket closed by remote

Post by De Kus »

Okay, I made a script which trys to get the real respondtime from a server by connecting, sending an empty line and closing the socket.
If I send the server an empty line it will close the socket without notice, so if the server does not close the socket, the process controlling the port is stalled. Can this somehow be indicated? I don't know a "stalled" server to check, so I dont know if my current code would already check it.
in my current version I believe EOF would be always true, because the server sends nothing and gets returns always -1 (meaning there is nothing to get).
Would it be wise to make a -async connection and a fileevent? but would fileevent trigger if there is only an EOF to read?

another thing, can I phrase the catch variable output if the connection failed due timeout or due closed port?

Code: Select all

proc getzwstatus {} {
	global zwstat zwping zwip
	set zwstart [clock clicks -milliseconds]
	if { [catch {set sock [socket $zwip 2593]}] } {
		set zwstat 0
	} else {
		puts $sock ""
		flush $sock
		gets $sock trash
		if { [eof $sock] } {
			set zwstat 1
		} else {
			set zwstat 2
		}
		close $sock
	}
	set zwping [expr {[clock clicks -milliseconds] - $zwstart}]
	return 0
}
btw. sorry if it was explained somewhere else, but I couldn't find something that would answer my problem.

PS:

Code: Select all

proc getzwstatus {} {
	global zwstat zwstart zwip
	set zwstart [clock clicks -milliseconds]
	set sock [socket -async $zwip 2593]
	puts $sock ""
	flush $sock
	fileevent $sock readable [list getzwstatus:cb $sock]
	return 0
}
	
proc getzwstatus:cb {sock} {
	global zwstat zwstart zwping
	gets $sock trash
	set trash2 [fconfigure $sock -error]
	set zwstat 1
	close $sock
	set zwping [expr {[clock clicks -milliseconds] - $zwstart}]
	putidx 10 "'$trash' '$trash2'"
	return 0
}
I tried now with fileevent, but no sign that the connections has been closed. Will fileevent only trigger on empty string input, when the socket has been closed? in this case I would only have to check if filevent didnt trigger for so and solong, wouldnt I?
A channel is also considered to be readable if an end of file or error condition is present on the underlying file or device. It is important for script to check for these conditions and handle them appropriately; for example, if there is no special check for end of file, an infinite loop may occur where script reads no data, returns, and is immediately invoked again.
yeah, but how do I get these errors? how can I check if the function is called, because of an error or because there is data to read? @_o. [fconfigure $sock -error] dosent return errors, if the socket has been closed remotely at least, havent tried yet, what it returns, if the socket connect has been refused.
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

you check if the connection is closed by using [eof] on fileevent readable channel

for example, a simple echo server (copied & pasted directly from [fblocked] manpage):

Code: Select all

# This is called whenever a new client connects to the server
proc connect {chan host port} {
    set clientName [format <%s:%d> $host $port]
    puts "connection from $clientName"
    fconfigure $chan -blocking 0 -buffering line
    fileevent $chan readable [list echoLine $chan $clientName]
}

# This is called whenever either at least one byte of input
# data is available, or the channel was closed by the client.
proc echoLine {chan clientName} {
    gets $chan line
    if {[eof $chan]} {
        puts "finishing connection from $clientName"
        close $chan
    } elseif {![fblocked $chan]} {
        # Didn't block waiting for end-of-line
        puts "$clientName - $line"
        puts $chan $line
    }
}

# Create the server socket and enter the event-loop to wait
# for incoming connections...
socket -server connect 12345
vwait forever
User avatar
De Kus
Revered One
Posts: 1361
Joined: Sun Dec 15, 2002 11:41 am
Location: Germany

Post by De Kus »

if I directly use this, then EOF will be true in the following cases:
a) connection to TCP port was refused
b) connection to TCP timed out
c) connection was closed after it was successfully opend

I am currently working with this code now:

Code: Select all

proc getzwstatus {} {
	global zwstat zwstart zwip
	if { ${::server-online} < [expr [unixtime] - 120] } {
		set zwstart [clock clicks -milliseconds]
		set sock [socket -async $zwip 2593]
		fconfigure $sock -blocking 0
		fileevent $sock writable [list getzwstatus:cb $sock]
	}
	return 0
}

proc getzwstatus:cb {sock} {
	if { [fconfigure $sock -error] == "" } {
		puts $sock ""
		flush $sock
		fileevent $sock readable [list getzwstatus:cb2 $sock]
	} else {
		set ::zwstat 0
		set ::zwping [expr {[clock clicks -milliseconds] - $::zwstart}]
	}
	fileevent $sock writable ""
	return 0
}
	
proc getzwstatus:cb2 {sock} {
	if { [fconfigure $sock -error] == "" } {
		set trash [read $sock]
		set ::zwstat 1
	} else {
		set ::zwstat 2
	}
	fileevent $sock readable ""
	close $sock
	set ::zwping [expr {[clock clicks -milliseconds] - $::zwstart}]
	return 0
}
however, this will create incredible ping results, seems filevent ist really really slow, it seems to trigger once a second so I will get always pings above 1500ms (where I had less than 300ms with blocking I/O). At least the TCL avaible from windrop.sourceforge.net and cygwin compiled eggdrop on winxp.

When outputting the ping I have an if to ask for ping > 20000 and then print "timeout". this at least gives me the correct TCP status, maybe I have do get the real ping with sync connection after checking asyncronly that the server is avaible (and the bot won't block 20sec for timeout).
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
Locked