mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Jul 2006
Posts: 4,149
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
In some cases (probably rare) mIRC doesn't actually re-trigger the on sockread event when it should:

Code:
alias tests {
sockclose test 
sockopen test www.youtube.com 80
}
on *:sockopen:test:{ 
sockwrite -n test GET /results?search_query=madonna HTTP/1.0
sockwrite -n test Host: www.youtube.com
sockwrite -n test
}
on *:sockread:test:{
var %test

;echo -a $sockerr $sock(test).rq

sockread -f %test
echo -a > %test

;sockread -f %test
;echo -a > %test
}

on *:sockclose:test:echo 4 -a CLOSED
The end of the source code of that page is actually:
Html:
if (window.yt.timing) {yt.timing.tick("js_foot");}    </script>



  <div id="debug">
    
  </div>

</body>
</html>
But using the above code and /tests, you actually get this as the last line:
Code:
if (window.yt.timing) {yt.timing.tick("js_foot");}    </script>
I left the comment so you can easily debug, if you use the second /sockread, you correctly get the last line. If you check $sock().rq, it returns the correct value.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Dec 2002
Posts: 344
D
Pan-dimensional mouse
Offline
Pan-dimensional mouse
D
Joined: Dec 2002
Posts: 344
That's not a bug. When ON SOCKREAD triggers, you must read the entire buffer's contents. That means looping until the buffer is empty. ON SOCKREAD only re-triggers if additional information has been added to the read buffer since last time it triggered, not merely if there is information in the buffer that you neglected to read last time.

Joined: Jul 2006
Posts: 4,149
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Either you or I is misunderstanding the help file:
Originally Posted By: /help on sockread
Note: A single /sockread may not be enough to read the entire buffer. You should keep reading until $sockbr (bytes read) is set to zero. This is far faster than letting mIRC re-trigger the event. If your script does not read the whole buffer, the on sockread event is re-triggered if:

a) you were reading into a &binvar.

b) you were reading into a %var and there is still a $crlf terminated line in the buffer waiting to be read.
I was reading into a %var and there is still a $crlf terminated line in the buffer waiting to be read so I think it's you wink
What you are describing doesn't even make sense. If by any chance the whole data is read by winsock and mirc triggers the event for the first time and you read the first line, mIRC would never trigger the event again, 99% of the socket script out there wouldn't work laugh

Last edited by Wims; 14/12/12 03:51 AM.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Dec 2002
Posts: 5,420
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,420
mIRC will discard data that is not read, depending on the context, so it is likely that the second context (b) is what is happening. It may be that using -f to force the read even if the line does not end in $crlf is causing the issue. In this context, the results will be random as received packets will vary in size depending on the network. If you check the last line received from the website, does it include a $crlf?

Last edited by Khaled; 14/12/12 07:15 PM.
Joined: Jul 2006
Posts: 4,149
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
I actually found the problem.
In fact, there's no $crlf, only a $lf lol.
mIRC is actually not retriggering the event correctly, but it is not filling the %variable correctly either, mIRC stops at a $lf instead of the end of the buffer if this $lf isn't preceded by a $cr, which can only happen when using -f, yeah.

/test to reproduce:
Code:
alias test test_server | client 1 | client 2 | .timer 1 3 sockclose test_?*
alias test_server socklisten test_server 8000
on *:socklisten:test_server:{
  if (!$sockerr) {
    var %socket test_cclient $+ $sock(test_cclient?*,0)
    bset -t &a 1 $+(mIRC,$lf,what else??) 
    sockaccept %socket
    sockwrite %socket &a
  }
}
alias client sockopen test_client $+ $1 127.0.0.1 8000
on *:sockread:test_client?*:{
  if (!$sockerr) {
    if ($sockname == test_client1) { var %a | sockread -f %a | echo -a client1 > %a }
    elseif ($sockname == test_client2) { sockread 16 &a | echo -a client2 > $bvar(&a,1-).text -- $bvar(&a,1-) }
  }
}


Last edited by Wims; 15/12/12 07:53 AM.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Dec 2002
Posts: 5,420
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,420
The socket routines only look for a $lf at the end of a line, they do not depend on a full $crlf. If there is a $cr before an $lf, it is also removed but it is not necessary.

What is happening is that if a line in the buffer does not end in a $lf and you previously used /sockread into a %var (meaning that you want $lf terminated lines), mIRC will not trigger the event again because there is no $lf terminated line in the buffer waiting to be read.

In your example, the line happens to be the last line sent by the server, so the only way to read it is to check in the SOCKCLOSE event if there is any data still in the buffer by using $sock().rq and then using /sockread -f to read it.

As far as I can tell, mIRC is behaving as expected, however many scripters may not not have anticipated this situation.

I could change the behaviour so that if a SOCKCLOSE event is triggered and there is still data in the buffer, a final SOCKREAD event is triggered. This would not work for scripts that use /sockread (without -f) which requires the line to end in a $lf. So in this final SOCKREAD, I would also need to change /sockread (without -f) to work like /sockread -f, forcing a read.

Sometimes it is difficult to know how far I should go to abstract away technicalities. Does anyone see any issues with the above change? Any backward compatibility issues?

Joined: Apr 2004
Posts: 871
Sat Offline
Hoopy frood
Offline
Hoopy frood
Joined: Apr 2004
Posts: 871
Originally Posted By: Khaled
Sometimes it is difficult to know how far I should go to abstract away technicalities. Does anyone see any issues with the above change? Any backward compatibility issues?

Yes, this would break at least one of my scripts, which uses "on SOCKREAD" to discard everything but the last (non-CRLF-terminated) line and then "on SOCKCLOSE" to read and process only that last line.

Please don't change this. The current behavior is just fine. If anything, the helpfile could be amended to cover correct usage of sockets in a bit more detail. For example, that for line-based processing, /sockread's -f flag should only ever be used from "on SOCKCLOSE". This is one of those things that people seem to get wrong all the time.


Saturn, QuakeNet staff
Joined: Jul 2006
Posts: 4,149
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Let me clarify, I was actually thinking mIRC was looking for $crlf terminated line ONLY (as mentioned and as usual, the help file is not explicit!), I now understand.
You shouldn't change how on sockread is triggered here, and as far as if you should abstract away technicalities, I think there are cases when it's a good idea and cases where it's not, in general I think you did it well, socket support is really well done in mIRC.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel

Link Copied to Clipboard