mIRC Homepage
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.
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.
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
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?
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-) }
  }
}

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?
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.
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.
© mIRC Discussion Forums