mIRC Homepage
Posted By: RRX when is $sockerr filled - 16/12/07 04:34 PM
The help file says:
"$sockerr is set to a value after each socket command/event and must be checked after each socket command and before processing an event to see if an error occurred."

Does that mean that everytime I /sockread in an on sockread command I have to check $sockerr?

Posted By: TropNul Re: when is $sockerr filled - 16/12/07 04:52 PM
Yes, because when interacting with a remote server/application, the client must check each received packet to see if an error occured.

Something like this will suffice.

Code:
If $sockerr { Echo -at - Error on $sockname - | Return }


Cordialement
Posted By: RRX Re: when is $sockerr filled - 16/12/07 06:37 PM
That would also mean that if a header is sent in on sockopen event, I have to check after every /sockwrite if $sockerr is > 0, I saw nobody doing that so far?
Posted By: starbucks_mafia Re: when is $sockerr filled - 16/12/07 07:20 PM
They should do, but many people don't bother with pesky things like error checking. Then one day when things break without any kind of error message they end up on a forum like this wondering what happened.
Posted By: DJ_Sol Re: when is $sockerr filled - 16/12/07 09:19 PM
lol


if ($sockerr > 0) { return }
Posted By: Trashlord_ Re: when is $sockerr filled - 17/12/07 01:05 AM
on *:sockwrite:*:{ if ($sockerr) { echo -at Write error: $sockname | halt } }
Posted By: TropNul Re: when is $sockerr filled - 17/12/07 03:41 AM
Originally Posted By: ""
That would also mean that if a header is sent in on sockopen event, I have to check after every /sockwrite if $sockerr is > 0, I saw nobody doing that so far?


No, the error check should be done only once, generally at the top of the event.

Let's take an example (which is the way things should be done)
Code:
On *:SockOpen:Name:{
  If $sockerr { Echo -st - Error on $sockname - | Return }
  Var %s = SockWrite -n $sockname
  %s NICK SomeNickname
  %s USER something something something :Just Testing
}


Of course, something like the following is useless.
Code:
On *:SockOpen:Name:{
  If $sockerr { Echo -st - Error on $sockname - | Return }
  Var %s = SockWrite -n $sockname
  %s NICK SomeNickname
  If $sockerr { Echo -st - Error on $sockname - | Return }
  %s USER something something something :Just Testing
  If $sockerr { Echo -st - Error on $sockname - | Return }
}

Because, in the case of an error, the socket is automatically closed by mIRC, so a unique check will do it. smile

NB: Note the use of "Var %s = SockWrite -n $sockname", which is not a compulsory method. I like to do that when I'll have to do a series of /sockwrite. It then neatens the source. It's only a matter of taste and aesthetics. smile
Posted By: RRX Re: when is $sockerr filled - 17/12/07 04:26 AM
Originally Posted By: TropNul
Originally Posted By: ""
That would also mean that if a header is sent in on sockopen event, I have to check after every /sockwrite if $sockerr is > 0, I saw nobody doing that so far?


No, the error check should be done only once, generally at the top of the event.

Let's take an example (which is the way things should be done)
Code:
On *:SockOpen:Name:{
  If $sockerr { Echo -st - Error on $sockname - | Return }
  Var %s = SockWrite -n $sockname
  %s NICK SomeNickname
  %s USER something something something :Just Testing
}


Of course, something like the following is useless.
Code:
On *:SockOpen:Name:{
  If $sockerr { Echo -st - Error on $sockname - | Return }
  Var %s = SockWrite -n $sockname
  %s NICK SomeNickname
  If $sockerr { Echo -st - Error on $sockname - | Return }
  %s USER something something something :Just Testing
  If $sockerr { Echo -st - Error on $sockname - | Return }
}

Because, in the case of an error, the socket is automatically closed by mIRC, so a unique check will do it. smile

NB: Note the use of "Var %s = SockWrite -n $sockname", which is not a compulsory method. I like to do that when I'll have to do a series of /sockwrite. It then neatens the source. It's only a matter of taste and aesthetics. smile

Thats rather contradiction, as said, according to the help, any of the /sockwrite's can cause $sockerr to be > 0, so if only a check after the on sockopen event, it would be possible that for example the first /sockwrite fails with an error, so the socket is then closed by mirc but the code from the event keeps running until the end, return or halt, so this would halt it with an error in status, and it's also possible a script has to perform certain code in case of failure so it has to check $sockerr everytime because mirc stops executing after an error and the script wouldnt be able to perform that code anymore (or it would need an :error label)
So an unique check will not do it then.

Another text from the help:
"On error: if a /sockwrite fails, it sets $sock().wserr to the error value, and triggers the on sockwrite event with $sockerr set."
The help really sucks when it comes to details.
It doesn't say it triggers the on sockwrite AFTER the current code has finished executing, so it would mean then that mIRC triggers the on sockwrite event with $sockerr check - immediately, similar to /signal -n (so far the only such case I know is when doing /disconnect, the on disconnect event is triggered, and then mirc proceeds executing the code after /disconnect)
It's all...guessing.

Posted By: TropNul Re: when is $sockerr filled - 17/12/07 05:25 AM
I'll try to clarify the issue. (I'm no socket expert though)

When the different events "On sockopen", "On sockwrite" and "On sockread" are triggered, any error that may have been received or sent can/must be detected at the top of the event directly without having to check for an error after each socket command. When you do /sockopen, "on sockopen" is triggered. When you do /sockwrite, "on sockwrite" is triggered (when all the data has been sent) and eventually, because of the /sockwrite, the remote application/server will produce a reply and that's when "on sockread" is triggered. Also, "on sockread" is triggered whenever you receive something remotely, whether you did a /sockwrite or not.

I mean by this that the "On sockopen" event should be coupled with a "On sockread" and/or with a "On sockwrite" event to be able to get the error (if any) when the remote server/application replies.

The "on sockopen" and "on sockwrite" only triggers when the client 'opens' and 'writes to' a socket and will produce only client errors. To be able to see the remote server's/application's errors (if any), you must use "on sockread" with the same "if $sockerr { return }" check on top.

Basically it should ressemble the following:
Code:
on *:sockopen:name:{
  if $sockerr { echo -st - $sockname error - $sock($sockname).wserr | return }
  commands
}
On *:sockread:name:{
  if $sockerr { echo -st - $sockname error - $sock($sockname).wserr | return }
  commands
}
on *:sockwrite:name:{
  if $sockerr { echo -st - $sockname error - $sock($sockname).wserr | return }
  commands
}

I don't know if I've been clear but I've tried to. :s

--
I'll add this to the explanation:

Even if an error occured for example as a consequence of the 7th /sockwrite in a 'on sockopen' event, the error would only be detected in the 'on sockwrite' event when all the contents of that /sockwrite have been sent!

Same when receiving data. Errors will be detected only when your mIRC actually receives the data, that is, when the 'on sockread' event is triggered.
--

Cordialement
Posted By: RRX Re: when is $sockerr filled - 17/12/07 03:47 PM
This is the reason for my subject:
Code:
on *:sockread:VIPCheck*: {
  if ($sockerr == 3) { echo -tac Highlight * error on connected socket occurred for $sockname ( $sock($sockname).wserr ) | halt }
  if ($sockerr) { echo -tac Highlight * Unknown sock error for $sockname | halt }
  var %data
  while (1) {
    sockread %data
    if (!$sockbr) break
    if ($sockerr == 3) { echo -tac Highlight * error on connected socket occurred for $sockname ( $sock($sockname).wserr ) | halt }
    if ($sockerr) { echo -tac Highlight * Unknown sock error for $sockname | halt }
    if (($regex(%data,/<user(?: (opped|voiced)="true"|())>([^<]+)<\/user>/)) && ($istok($gettok($sock($sockname).mark,2-,32),$regml(2),32))) {
      if (($regml(1) == opped) && ($me isop $gettok($sock($sockname).mark,1,32)) && ($regml(2) ison $v2) && ($v1 !isop $v2)) .mode $v2 +o $v1
    }
  }
}

I was surprised to see $sockerr checks in the loop that reads from the socket.
Is this needed or not?
Posted By: TropNul Re: when is $sockerr filled - 17/12/07 04:56 PM
Well, if the coder wants to have a different error message when $sockerr equals to 3, then the method is quite good (though, imho, too much ifs are used here).

Have in mind that, for each on sockread trigger, $sockerr is allocated only one value(0 = no error, 1-n = error), so checking it at different stages won't change its value.

In the example you posted, the coder just wanted to have the error message for $sockerr = 3 displayed. Now, the while loop is not necessary when sockreading sockets. I would do something like this instead.

Code:
on *:sockread:VIPCheck*: {
  if $sockerr {
    echo -tac Highlight * $iif(($v1 == 3),error on connected socket occurred for $sockname $sock($sockname).wserr,Unknown sock error for $sockname)
    return
  }
  var %data
  sockread %data
  if (!$sockbr) return
  elseif (($regex(%data,/<user(?: (opped|voiced)="true"|())>([^<]+)<\/user>/)) && ($istok($gettok($sock($sockname).mark,2-,32),$regml(2),32))) {
    if (($regml(1) == opped) && ($me isop $gettok($sock($sockname).mark,1,32)) && ($regml(2) ison $v2) && ($v1 !isop $v2)) .mode $v2 +o $v1
  }
}


Hope this helped.

Cordialement
Posted By: RRX Re: when is $sockerr filled - 17/12/07 05:34 PM
Originally Posted By: TropNul

Have in mind that, for each on sockread trigger, $sockerr is allocated only one value(0 = no error, 1-n = error), so checking it at different stages won't change its value.

Then the $sockerr checks inside the loop are useless, thats what I wanted to know.

Regarding the looping, the help says its better to loop instead of letting mirc retriggering the event, the first is much faster.
Posted By: DJ_Sol Re: when is $sockerr filled - 17/12/07 11:47 PM
I dont know if this will help, but this is what I have learned.

on *:Sockread:sockname:{
if ($sockerr > 0) { return }


sockread lines



:error
if ($error) { echo -s $error | reseterror }
}

Notice I use return instead oh halt. This is so mIRC doesn't halt all currently running scripts. Only the one that has the error.
Posted By: RRX Re: when is $sockerr filled - 21/12/07 06:39 AM
Originally Posted By: DJ_Sol
I dont know if this will help, but this is what I have learned.

on *:Sockread:sockname:{
if ($sockerr > 0) { return }


sockread lines



:error
if ($error) { echo -s $error | reseterror }
}

Notice I use return instead oh halt. This is so mIRC doesn't halt all currently running scripts. Only the one that has the error.

So far I use only a $sockerr check in the beginning of a socket event, unlike what is done in the script piece I pasted, it also checks after every /sockread and my question was if a /sockread can make $sockerr have a new value, for example, the on sockread triggers, no error ($sockerr 0), but after the first (or 12th, doesnt matter), if its possible that it suddenly does get a value (and important remind: all in the execution time of this same on sockread event).

That :error label is not related to my question, I was talking ab out the $sockerr identifier.

Btw, (offtopic), /halt only halts the execution from the event that is executed, halt will not stop mirc from executioning another event with the same triggering conditions (in another file ofcourse, because implementation causes it to only execute the first instance if both are in same scriptfile.
So there is nothing wrong with using /halt instead of /return, in an event.
The place where this choice does make a difference is an alias, if /halt is used there, it will stop the execution of the whole currently processed code, so also the calling place, no matter how many levels.
Posted By: RRX Re: when is $sockerr filled - 19/01/08 05:21 PM
Originally Posted By: starbucks_mafia
They should do, but many people don't bother with pesky things like error checking. Then one day when things break without any kind of error message they end up on a forum like this wondering what happened.

/sockread reads from a socket buffer, right?
I assume this buffer is located in memory from the mIRC process, right?
Now, suppose mIRC is busy processing an on sockread event, can I assume 'mIRC busy' means that it doesn't receive new data inside the mIRC socket buffer, because the operating system cannot pass it to mIRC since it's not ready (busy processing on sockread event)?

If above is true, then $sockerr cannot change since mIRC started processing the on sockread event. Also, the amount bytes in the mIRC socketbuffer can only drop equal bytes as /sockread reads.
Maybe put in another way: suppose on sockread event triggers, the total bytes in the buffer is 1000, if you make the sum of all $sockbr's after /sockreads, it can only be 1000 if you read until $sockbr == 0 and never higher?
Posted By: Ninko Re: when is $sockerr filled - 25/03/08 05:10 PM
Hi there,
A question here which is kinda related to this topic.

When a sockread event is triggered I work out the size of the file and compare it using $sock(sockname).rcvd to know when I have got everything in the file, at which time I break out of the sockread loop. Or at least thats the idea.

So far it only works when I allow mIRC to re-trigger the sockread event, rather then trigger once and loop till finished because it would 'appear' that $sock(sockname).rcvd only updates after the code finishes, and of course when looping that will be never if $sock(sockname).rcvd never updates.

Any info on this would be great!

Thanks


Ninko
Posted By: argv0 Re: when is $sockerr filled - 25/03/08 05:57 PM
you should know how many bytes you received every loop iteration, just keep a local count.

Code:
var %x = $sock($sockname).rcvd
while ($true) {
  sockread &bvar
  inc %x $sockbr
  if ($sockbr == 0 || %x >= %THEFILESIZE) break
}
Posted By: Ninko Re: when is $sockerr filled - 26/03/08 12:31 PM
So, this wouldn't work is what your saying, you must use $sockbr in loops?

Code:
:start
sockread &bvar
%x = $sock(sockname).rcvd
if (%x == %THEFILESIZE) {
  code etc
}
else {
  goto start
}



Ninko
Posted By: Ninko Re: when is $sockerr filled - 26/03/08 12:48 PM
I just did a little test.

Code:
  %1 = 0
  :test
  sockread &temp
  bwrite etc etc &temp
  %x = $sock(sockname).rcvd
  echo -a %x %THEFILESTZE $sockbr
  %1 = %1 + 1
  if (%1 == 10) { halt }
  else { goto test }


The results were:

289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
4385 17935 4096
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
8481 17935 4096
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
12577 17935 4096
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
16673 17935 4096
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
17935 17935 1262
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0

So once again, $sock(sockname).rcvd doesn't update untill re-triggered along with $sockbr.

Am I missing something here?


Ninko
Posted By: Ninko Re: when is $sockerr filled - 27/03/08 12:33 AM
Must just be me then...


Ninko
Posted By: argv0 Re: when is $sockerr filled - 27/03/08 12:42 AM
I think you're misinterpreting how $sockbr is used

$sockbr returns the number of bytes you got from the very last /sockread call, which reads from the queue buffer.

If there is nothing in the queue, and nothing left to read then it naturally returns 0.

This is normal. Your results reflect this behaviour. You'll see that you loop 10 times and that the entire queue is read in the very first /sockread each time, leaving nothing left to read for the next 9 sockreads.

as far as .rcvd goes, you correctly point out that it updates after the sockread event only.. so as I mentioned, to keep score inside a specific sockread event you have to count with $sockbr.

I also gave you the code to do this. Where does the confusion lie?
Posted By: Ninko Re: when is $sockerr filled - 27/03/08 12:53 AM
But why does it not keep reading more from the buffer when theres clearly more, it only carries on after the code has stopped and re-triggered. The help file says its quicker to keep reading rather then let it re-trigger, but all I see is it making problems...

If you look at my results its re-triggered many times after the 10 time loop...

289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
289 17935 0
re-triggered here
4385 17935 4096
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
4385 17935 0
re-triggered here
8481 17935 4096
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
8481 17935 0
re-triggered here
12577 17935 4096
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
12577 17935 0
re-triggered here
16673 17935 4096
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
16673 17935 0
re-triggered here
17935 17935 1262
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0
17935 17935 0


Ninko
Posted By: starbucks_mafia Re: when is $sockerr filled - 27/03/08 01:34 AM
The reason is that you're using /sockread &binvar which is a special case where looping isn't going to help because it will read the entire contents of the socket buffer into the binary variable at once. That means any subsequent looping won't read anything because the buffer won't be re-filled until the sockread event ends.

For any other usage of the /sockread command however looping will be useful because there will be no guarantee that the entire buffer will be read at once. For example if you change that line to something like /sockread 1000 &temp or /sockread -n &temp then you'll see that $sockbr does update correctly when there's more data to be read from the buffer.
Posted By: argv0 Re: when is $sockerr filled - 27/03/08 01:46 AM
The socket buffer is 4096 bytes, you've read it all-- mIRC has nothing left to sockread until next ON SOCKREAD event.
Posted By: Ninko Re: when is $sockerr filled - 27/03/08 03:07 AM
So in this case I need to let it re-trigger its self? I don't mind either way, I was just going by the mIRC help file when it says its better to loop it rather then allow mIRC re-trigger.


Ninko
Posted By: argv0 Re: when is $sockerr filled - 27/03/08 03:21 AM
No-- you should loop-- this does not go against the help file.

but you should realize that if you /sockread 4096 bytes (the default for a binvar) you will exhaust the buffer and there will never be anything left to read...

so you can and *should* loop, but realize that if you're reading the default binvar size it will probably never actually iterate more than once-- you might want to keep the loop code though, just in case you change the read size down from 4096 in the future for some reason.

Code:
while ($true) {
  sockread &bvar
  if ($sockbr == 0) break
}


You'll see that only triggers once, but if you change the numbytes param on /sockread:

Code:
while ($true) {
  sockread 1024 &bvar
  if ($sockbr == 0) break
}


It would iterate ~4 times (for a full buffer).
Posted By: Ninko Re: when is $sockerr filled - 27/03/08 03:29 AM
So if I lower the amount the binvar will read at a time, it will allow the buffer to update as the rest of the file comes in (the file size is 17965 bytes)? or am I still not understanding...

Code:
%1 = 0
:test
sockread 1024 &temp
bwrite etc etc &temp
%x = $sock(sockname).rcvd
echo -a %x %THEFILESTZE $sockbr
%1 = %1 + 1
if (%1 == 10) { halt }
else { goto test }


That would work then?


Ninko
Posted By: jaytea Re: when is $sockerr filled - 27/03/08 10:04 AM
right, but since the receive queue is maximally 4096 bytes, and mirc is able to read all 4096 bytes in a single /sockread &var, the point was not using a while loop in that case is the simplest and most efficient way forward

about the %1 business in your code, in general you should loop until $sockbr (after a /sockread) or $sock().rq become 0. here's yet another template code in addition to the one mentioned earlier, this is just to read a line at a time but any other sockread variation can be used as well:

Code:
on *:sockread:name:{
  var %var
  while ($sock($sockname).rq) {
    sockread -f %var
    echo -a * %var
  }
}
Posted By: Ninko Re: when is $sockerr filled - 27/03/08 01:11 PM
Ok ok, lets just forget all code for a min. The file I'm trying to download as I said is around 17965 bytes. And I think your saying the buffer can only hold 4096 bytes at a time? So of course it will take more then one buffer load to get the whole thing.

So what I'm asking here, does the code have to stop before the buffer will get the next load? I think we've already made the point about once you've read the whole buffer theres nothing more to read, but I was exspecting the buffer to update with the next load as the code went on.


Ninko
Posted By: jaytea Re: when is $sockerr filled - 27/03/08 02:47 PM
at the high level that is mircscript, yes, the code has to stop (the end of the sockread event must be reached) before mirc retriggers on *:sockread and gives you a new batch of data to handle
Posted By: Ninko Re: when is $sockerr filled - 27/03/08 05:02 PM
Right, now I understand, thats what I was getting at lol.


Ninko
Posted By: RRX Re: when is $sockerr filled - 10/08/08 08:27 AM
Originally Posted By: jaytea
at the high level that is mircscript, yes, the code has to stop (the end of the sockread event must be reached) before mirc retriggers on *:sockread and gives you a new batch of data to handle

Quote:

$sockerr

$sockerr is set to a value after each socket command/event and must be checked after each socket command and before processing an event to see if an error occurred.

that line should better be wiped from the help then, it's not true and in contradiction with the help example
Code:
on 1:sockread:testing:{
 if ($sockerr > 0) return
 :nextread
 sockread %temp
 if ($sockbr == 0) return
 if (%temp == $null) %temp = -
 echo 4 %temp
 goto nextread
}

... where it also does not check after /sockread

The $sockerr help line causes people to wrongly think $sockerr can change after each socket command, the word 'must' is even in bold.
It's also contradictional with the /sockwrite help:
Quote:

On error: if a /sockwrite fails, it sets $sock().wserr to the error value, and triggers the on sockwrite event with $sockerr set.



© mIRC Discussion Forums