From WikiChip
Editing mirc/commands/sockread

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

This page supports semantic in-text annotations (e.g. "[[Is specified as::World Heritage Site]]") to build structured and queryable content provided by Semantic MediaWiki. For a comprehensive description on how to use annotations or the #ask parser function, please have a look at the getting started, in-text annotation, or inline queries help pages.

Latest revision Your text
Line 1: Line 1:
{{mirc title|/sockread Command}}
+
{{mIRC menu}}
 
The '''/sockread''' command reads bytes from the receive buffer of a socket connection into a specified variable. This command must be and is to be used inside socket events.
 
The '''/sockread''' command reads bytes from the receive buffer of a socket connection into a specified variable. This command must be and is to be used inside socket events.
  
 
mIRC in general only understand {{mIRC|$crlf}} terminated line. With socket, mIRC only understands {{mIRC|$lf}} terminated line (any {{mirc|$cr}} before a {{mirc|$lf}} is removed).
 
mIRC in general only understand {{mIRC|$crlf}} terminated line. With socket, mIRC only understands {{mIRC|$lf}} terminated line (any {{mirc|$cr}} before a {{mirc|$lf}} is removed).
  
The number of bytes waiting to be read can be retrieved using {{mIRC|$sock|$sock(name).rq}}
+
The number of bytes waiting to be read can be retrieved using {{mIRC|$sock|$sock(name).rq)
  
 
By default:
 
By default:
Line 20: Line 20:
  
 
== Switches ==
 
== Switches ==
{| class="wikitable" style="line-height: 25px;"
+
{| class="wikitable" style="line-height: 25px; margin-left: 75px;"
 
|-
 
|-
 
! Switch !! Description
 
! Switch !! Description
Line 30: Line 30:
  
 
== Parameters ==
 
== Parameters ==
{| class="wikitable" style="line-height: 25px;"
+
{| class="wikitable" style="line-height: 25px; margin-left: 75px;"
 
|-
 
|-
 
! Parameter !! Description
 
! Parameter !! Description
Line 46: Line 46:
 
     b) you were reading into a %var and there is still a terminated line in the buffer waiting to be read.  
 
     b) you were reading into a %var and there is still a terminated line in the buffer waiting to be read.  
  
This means you will miss the last line if it is not a terminated line and you are reading line by line only (and not in a binvar, although it's also easier to use on sockclose with binvar if you are reading line by line and facing this). You can read that line in the on sockclose event, {{mIRC|/sockread#Last line not showing up|see below}}.
+
This means you will miss the last line if it is not a terminated line and you are reading line by line only. You can read that line in the on sockclose event.
 
 
'''Note''' (fixed since mIRC 7.36): Using SSL, on sockread might not be retriggered as it should, {{mIRC|on events/on sockclose|on sockclose}} will be triggered too early with $sockerr sets to 3, you must read the receive buffer from that event
 
  
 +
'''Note''': Using SSL, on sockread might not be retriggered as it should, {{mIRC|on sockclose}} will be triggered too early with $sockerr sets to 3, you must read the receive buffer from that event
  
 
It is important to note that the data received will vary in size. Practically speaking, we receive several kilobytes per second, it is easy to assume that the data you want is going to be sent and received the same way and above all, the way you want, but that's incorrect, you might receive very small packet at a very small speed.
 
It is important to note that the data received will vary in size. Practically speaking, we receive several kilobytes per second, it is easy to assume that the data you want is going to be sent and received the same way and above all, the way you want, but that's incorrect, you might receive very small packet at a very small speed.
Line 72: Line 71:
 
  }
 
  }
 
}</source>
 
}</source>
If you do that, you cannot guarantee it will work 100% of the time.
+
You might think that
 
+
If you do that, you cannot guarantee it will work 100% of the time, if the received buffer is filled with a few bytes and ends up being "this is my ref" when on sockread triggers, the -f switch will force mirc to read that, and you won't be able to match your full line, for example here, the next time the event triggers, you might have a received buffer containing "erence:", but it might be "erence:\r\nI want that line" as well.  
If the received buffer is filled with a few bytes and ends up being "this is my ref" when on sockread triggers, the -f switch will force mirc to read that, and you won't be able to match your full line, for example here, the next time the event triggers, you might have a received buffer containing "erence:", but it might be "erence:\r\nI want that line" as well, screwing you anyway.
 
  
 
So you might think here "let's not use -f then":
 
So you might think here "let's not use -f then":
Line 87: Line 85:
 
}</source>
 
}</source>
  
And that, assuming what you are looking for is not on the last non terminated line (which would be missed because -f is not there, although note that you can read that last non terminated line inside the {{mIRC|on sockclose}} event), should be fine. In fact, in this specific example and in general, it will work, because you are making sure %a is a full line or nothing. Well that's why it works in most situation, you are checking that %a is a specific text, which would fail if no byte were read into %a because a terminated line couldn't be found. However, if you are in a situation where you must check that %a is $null (usually because it read an empty $crlf line), you must check {{mIRC|$sockbr}} to know if you read bytes at all, a good example of this usage is shown below, which discard the headers of HTTP (check for an empty value after /Sockread %a reads an empty $crlf line):
+
And that assuming what you are looking for is not on the last non terminated line (which would be missed because -f is not there), this should be fine. In fact, in this specific example and in general, it will work, because you are making sure %a is a full line or nothing. Well that's why it works in most situation, you are checking that %a is a specific text, which would fail if no byte were read into %a because a terminated line couldn't be found. If you are in a situation where you must check that %a is $null (usually because it read an empty $crlf line), you must check {{mIRC|$sockbr}} to know if you read bytes at all, a good example of this usage is shown below, which discard the headers of HTTP (check for an empty value after /Sockread %a reads an empty $crlf line):
  
 
<source lang="mIRC">
 
<source lang="mIRC">
Line 158: Line 156:
  
 
'''General Note''': it can be a good idea and might be simpler for you to read everything to a file and then parse that file.
 
'''General Note''': it can be a good idea and might be simpler for you to read everything to a file and then parse that file.
 
== Last line not showing up ==
 
 
Another common problem is reading the last line sent by an HTTP server, which isn't a terminated line (no $crlf or $lf).
 
 
Indeed, if you are using /sockread %var, you're will read properly line by line but that last line won't be read by this sockread command.
 
 
We also saw how this non terminated line in the received buffer wouldn't make mIRC retrigger the on sockread event.
 
 
One solution which doesn't involve more than that, is to read that line from the on sockclose event, indeed you are sure on sockread read the previous line, so inside on sockclose, you should get only that last non terminated line, this time we use the -f switch to force the read:
 
 
<source lang="mIRC">
 
on *:sockclose:name:{
 
  if (!$sockerr) {
 
  var %a
 
  sockread -f %a
 
  if ($sockbr == 0) return
 
  echo -a > %a
 
}
 
}
 
</source>
 
 
If you are using HTTP 1.1 and you actually want the socket to remain open, you would need to grab the value of the content-length header, store that in a variable and increase another variable with the length of what you are reading, if the length of the received buffer + the value of that variable equal the value of the content length, you should first try to see if you have a line by reading with /sockread %a, and if no byte is read, then use /sockread -f %a.
 
  
 
== Example ==
 
== Example ==
Line 190: Line 165:
 
'''Note2''': too long line will produce an error.
 
'''Note2''': too long line will produce an error.
  
'''Note3''': Using SSL, the on sockread event might not be triggered though it should, you must read the rest in the on sockclose event (has been fixed since mIRC 7.36).
+
'''Note3''': Using SSL, the sockread might not be triggered though there are still datas to be read, you must read the rest in the on sockclose event.
  
 
<source lang="mIRC">ON *:SOCKREAD:mySocket:{
 
<source lang="mIRC">ON *:SOCKREAD:mySocket:{
Line 204: Line 179:
 
</source>
 
</source>
  
'''Note''': as we just saw, if the last line in the source does not end with a terminated line, it won't be read by that event.
+
'''Note''': if the last line in the source does not end with a terminated line, it won't be read by that event, you might want to read that last line inside the on sockclose event. We can't use -f on sockread because it would allow the code to display whatever is in the buffer even if no terminated line is present.
  
 
If you ever worked with HTTP 1.1, you know that it can send data in chunk, here is a way to write the real content to a file:
 
If you ever worked with HTTP 1.1, you know that it can send data in chunk, here is a way to write the real content to a file:
Line 230: Line 205:
 
       else {
 
       else {
 
         var %a
 
         var %a
         sockread %a
+
     
         ;skip empty line
+
         ;when we start, the next line is the chunk size, but after reading a chunk, we must parse the $crlf ending that chunk
         while ($sockbr) && (%a == $null) { sockread %a }
+
         ;so if we read and %a is $null, it means we are after the start, we try to read the next line, if we can't find the next chunk in the current receive buffer, we return and allow the event to retrigger with more data.
 +
        sockread -f %a
 +
         while ($sockbr) && (%a == $null) { sockread -f %a }
 
         if (!$sockbr) || (%a == $null) return
 
         if (!$sockbr) || (%a == $null) return
 
         ;last chunk
 
         ;last chunk

Please note that all contributions to WikiChip may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see WikiChip:Copyrights for details). Do not submit copyrighted work without permission!

Cancel | Editing help (opens in new window)