From WikiChip
Editing mirc/sockets/tcp
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 Guide}} |
+ | {{Preknow|This article assumes that you have intermediate to advanced knowledge of the [[mIRC Scripting Language]] and familiarity with [[On events - mIRC|on events]] and [[Aliases - mIRC|custom aliases]].}} | ||
− | + | This tutorial is the '''TCP Sockets''' continuation of the [[Sockets - mIRC|Sockets (Intro) tutorial]]. If you haven't read that, please do so first before moving on to this one. | |
Now that you have some familiarity with the different types of sockets we can go into the scripting aspect of things. The most common task scripters want to perform is retrieving a piece data from some website. | Now that you have some familiarity with the different types of sockets we can go into the scripting aspect of things. The most common task scripters want to perform is retrieving a piece data from some website. | ||
Line 8: | Line 9: | ||
== Creating a Connection == | == Creating a Connection == | ||
− | Before we can do anything else we must first create a new connection to a specific address on a given port. | + | Before we can do anything else we must first create a new connection to a specific address on a given port. The syntax to do this: |
<syntaxhighlight lang="mirc">sockopen <handle> <address> <port></syntaxhighlight> | <syntaxhighlight lang="mirc">sockopen <handle> <address> <port></syntaxhighlight> | ||
Line 20: | Line 21: | ||
=== IPv4 vs. IPv6 Sockets === | === IPv4 vs. IPv6 Sockets === | ||
− | The /sockopen command is directly influenced by the | + | The /sockopen command is directly influenced by the type of connection you have going on (I.e. /server -4/-6). When in standard IPv4 mode, /sockopen can only operate in IPv4 mode. It is not possible to make IPv6 sockets. When in IPv6, /sockopen will default to IPv6 addresses only. By going to the Option Dialog: |
+ | |||
+ | (Alt+O) -> Connect -> Options -> Ports... -> [X] Prioritize IPv6 over IPv4 | ||
+ | |||
+ | Checking that checkbox will allow you to create IPv4 connections as well by telling mIRC to fall back to IPv4 if IPv6 failed. | ||
+ | |||
+ | '''Note:''' There is currently no convenient way to do this only using the /sockopen command. | ||
=== Connection Example === | === Connection Example === | ||
Line 31: | Line 38: | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
− | The above alias will create a socket by the name "example1". We can use that name to manipulate our socket | + | The above alias will create a socket by the name "example1". We can use that name to manipulate our socket late on. As a precaution, in order to not attempt to open an already opened socket, we will close it. If the socket is not open, mIRC will simply do nothing. In the advanced part of this tutorial we will explain how to handle this situation more gracefully by creating dynamic names which will give us the ability to create as many sockets as we need. |
<syntaxhighlight lang="mirc">alias example1 { | <syntaxhighlight lang="mirc">alias example1 { | ||
Line 55: | Line 62: | ||
== The Socket Mark == | == The Socket Mark == | ||
− | In the example above we introduced another command, the | + | In the example above we introduced another command, the [[/sockmark command - mIRC|/sockmark]] command. The [[/sockmark command - mIRC|/sockmark]] command lets you store some text for that socket which can easily be retrieved using the [[$sock identifier - mIRC|$sock().mark]] identifier later on. This is a better alternative to using a global variables (or any other kind of global storage method) and having to clean it up later. The socket mark goes away automatically with the socket. |
<syntaxhighlight lang="mirc">sockmark <handle> <value> | <syntaxhighlight lang="mirc">sockmark <handle> <value> | ||
Line 61: | Line 68: | ||
sockmark <handle></syntaxhighlight> | sockmark <handle></syntaxhighlight> | ||
− | The socket mark is restricted to the same line limit as the rest of mIRC (just under 4,150 bytes). A | + | The socket mark is restricted to the same line limit as the rest of mIRC (just under 4,150 bytes). A wildcard pattern can be used in the handle parameter to set the value of multiple sockets at once. |
<syntaxhighlight lang="mirc">; Our socket mark value: | <syntaxhighlight lang="mirc">; Our socket mark value: | ||
Line 67: | Line 74: | ||
== Transmitting a Request After a Successful Connection == | == Transmitting a Request After a Successful Connection == | ||
− | When a successful connection to the remote end-point has been established | + | When a successful connection to the remote end-point has been established the on sockopen event will trigger. Inside the on sockopen event we must send our initial request which would depend on what our script wants to do. A typical script that utilizes the HTTP protocol must send its headers in this event. |
− | '''Note:''' If a connection failed, on sockopen will also trigger, the difference this time is that $sockerr is set, see the Error Handling section | + | '''Note:''' If a connection failed, on sockopen will also trigger, the difference this time is that $sockerr is set, see the Error Handling section for more informations. |
− | The | + | The syntax for the on sockopen event is: |
<syntaxhighlight lang="mirc">on *:sockopen:<handle>: { | <syntaxhighlight lang="mirc">on *:sockopen:<handle>: { | ||
Line 77: | Line 84: | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
− | As we said before, from within the sockopen event we must send our request to the remote end-point. To send data to the remote end-point through the socket we use the | + | As we said before, from within the sockopen event we must send our request to the remote end-point. To send data to the remote end-point through the socket we use the /sockwrite command. The sockwrite command has the following syntax: |
<syntaxhighlight lang="mirc">sockwrite [-tn] <name> <text|%var|&binvar> | <syntaxhighlight lang="mirc">sockwrite [-tn] <name> <text|%var|&binvar> | ||
Line 83: | Line 90: | ||
sockwrite -b[tn] <name> <numbytes> <text|%var|&binvar></syntaxhighlight> | sockwrite -b[tn] <name> <numbytes> <text|%var|&binvar></syntaxhighlight> | ||
− | By default, all space-delimited tokens that begin with the | + | By default, all space-delimited tokens that begin with the & symbol are treated as binary variables. The -t switch can be used to make the /sockwrite command treat it all as plain text instead. |
=== The Sockwrite -n Switch and $crlf === | === The Sockwrite -n Switch and $crlf === | ||
− | Because the sockwrite command can be used to send any type of data you must be very explicit about the data you are sending. If you want to send multiple lines, you must append a $crlf to the end of your data. Alternatively you can also use the -n switch which will append a $crlf automatically for you | + | Because the sockwrite command can be used to send any type of data you must be very explicit about the data you are sending. If you want to send multiple lines, you must append a $crlf to the end of your data. Alternatively you can also use the -n switch which will append a $crlf automatically for you. |
Consider the following piece of code: | Consider the following piece of code: | ||
Line 116: | Line 123: | ||
Understanding this concept is important to understanding how to send data correctly via protocols like HTTP. | Understanding this concept is important to understanding how to send data correctly via protocols like HTTP. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=== Sending Data Example === | === Sending Data Example === | ||
Line 145: | Line 145: | ||
sockwrite -n YouTube GET /watch?v= $+ $sock($sockname).mark HTTP/1.1 | sockwrite -n YouTube GET /watch?v= $+ $sock($sockname).mark HTTP/1.1 | ||
sockwrite -n YouTube Host: www.youtube.com | sockwrite -n YouTube Host: www.youtube.com | ||
− | sockwrite -n YouTube | + | sockwrite -n YouTube $crlf |
}</syntaxhighlight> | }</syntaxhighlight> | ||
Line 153: | Line 153: | ||
<pre>http://www.example.com/foo.php?request&name=value</pre> | <pre>http://www.example.com/foo.php?request&name=value</pre> | ||
− | If we want to send | + | If we want to send that includes characters like the '=', '?' and '&' we must be escaped before they can be safely used. The exact rules are specified by the RFC 1738 (Top of page 3). |
We will use the following aliases to encode and decode URLs: | We will use the following aliases to encode and decode URLs: | ||
Line 160: | Line 160: | ||
alias urlEncode return $regsubex($1, /(\W)/g, $+(%, $base($asc(\t), 10, 16, 2))) | alias urlEncode return $regsubex($1, /(\W)/g, $+(%, $base($asc(\t), 10, 16, 2))) | ||
; Decode encoded URLs | ; Decode encoded URLs | ||
− | alias urlDecode return $regsubex($replace($1, +, $chr(32)), /%([A-F\d]{2})/gi, $chr($base(\1, 16, 10))) | + | alias urlDecode return $regsubex($replace($1, +, $chr(32)), /%([A-F\d]{2})/gi, $chr($base(\1, 16, 10)))</syntaxhighlight> |
− | |||
− | |||
− | |||
− | |||
− | </syntaxhighlight> | ||
Consider the following example: | Consider the following example: | ||
Line 180: | Line 175: | ||
<syntaxhighlight lang="mirc">on *:SockOpen:example: { | <syntaxhighlight lang="mirc">on *:SockOpen:example: { | ||
− | sockwrite -n example GET /foo/bar.php?foo= $+ $urlEncode( | + | sockwrite -n example GET /foo/bar.php?foo= $+ $urlEncode($input1) HTTP/1.1 |
sockwrite -n example Host: www.example.com | sockwrite -n example Host: www.example.com | ||
sockwrite -n example $crlf | sockwrite -n example $crlf | ||
Line 186: | Line 181: | ||
== POST vs GET? == | == POST vs GET? == | ||
− | By now you are probably asking yourself why did I use GET in our sockopen and how do you | + | By now you are probably asking yourself why did I use GET in our sockopen and how do you what to use. In HTTP, there are two methods for sending data to the server: '''POST''' and '''GET'''. They only differ in the format we send that data. When requesting a normal page, you will most likely be using the GET method, when submitting a form; however, it might get a little tricky. When dealing with forms, by simply looking at the source code you can tell if it's a POST or a GET method: |
<form id="FooBar" '''method="post"''' action=""> | <form id="FooBar" '''method="post"''' action=""> | ||
Line 202: | Line 197: | ||
GET /folder/file.html HTTP/1.1 | GET /folder/file.html HTTP/1.1 | ||
− | This line is made up of three parts: method, path and version. The "GET", which SHOULD be always in uppercase letters, is the method. For more information about the POST method see the advanced part of this tutorial. The next part is the path, relative to the root folder of the website. If our | + | This line is made up of three parts: method, path and version. The "GET", which SHOULD be always in uppercase letters, is the method. For more information about the POST method see the advanced part of this tutorial. The next part is the path, relative to the root folder of the website. If our website is www.example.com/pub/foo/bar.html, our path would be /pub/foo/bar.html. Lastly, the final part of this line is the HTTP version, for all practical reasons, you will probably using version 1.0. Sometimes we might need to use version 1.1 if we want features that are only available in that version. |
− | '''Note:''' For all | + | '''Note:''' For all particle purposes the HTTP RFC states that casing should not. Unfortunately, I came across multiple web servers that only accepted it in the exact casing we present in here. It's best to follow that rule as well. |
Next is the Host header: | Next is the Host header: | ||
Line 213: | Line 208: | ||
== Reading Incoming Data == | == Reading Incoming Data == | ||
− | Once the server receives your request, it will send the response back to you. This will trigger the | + | Once the server receives your request, it will send the response back to you. This will trigger the on sockread event. The basic syntax of the on sockread event is: |
<syntaxhighlight lang="mirc">on *:sockread:<handle>: { | <syntaxhighlight lang="mirc">on *:sockread:<handle>: { | ||
Line 219: | Line 214: | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
− | The on sockread will most likely be the hardest and longest part of your code. When the on sockread | + | The on sockread will most likely be the hardest and longest part of your code. When the on sockread triggers, you have to read the data and decide what to do with it. If your script just needs some information from that page you will have to find and parse the appropriate line. |
− | When it comes to HTTP, the data you will receive from the server will contain a header | + | When it comes to HTTP, the data you will receive from the server will contain a header follows by a blank line which will follow by the content of the page. The content of the will look identical to that text you find when you right click on a web page and click on view source code. |
− | + | '''Note:''' The on sockread event will trigger for every line the server replies. | |
− | To read a single line from the socket, we use the /sockread command | + | To read a single line from the socket, we use the /sockread command: |
− | <syntaxhighlight lang="mirc">sockread < | + | <syntaxhighlight lang="mirc">sockread <var></syntaxhighlight> |
− | + | The sockread command actually reads up to a $crlf. This is important to know because many web pages don't end with a $crlf which means the last line won't be read. The -f switch can be used to force the sockread command to read the line even if it does not end with a $crlf. | |
'''Note:''' If the variable does not exist, a global variable gets created. It is therefore advised to declare a local variable beforehand. | '''Note:''' If the variable does not exist, a global variable gets created. It is therefore advised to declare a local variable beforehand. | ||
Line 237: | Line 232: | ||
<syntaxhighlight lang="mirc">sockread [numbytes] <&binvar></syntaxhighlight> | <syntaxhighlight lang="mirc">sockread [numbytes] <&binvar></syntaxhighlight> | ||
− | + | There is a -n switch which can be used to read $crlf-terminated lines into the binary variable as well. | |
− | |||
=== Debugging === | === Debugging === | ||
− | Because the on sockread triggers when we get | + | Because the on sockread triggers when we get out data, it is the most interesting part of our script. Many people find it easier to script and debug when they can see the entire page source code. The script below can be used to see everything the server sent us in a custom window (@ $+ sockname): |
<syntaxhighlight lang="mirc">;Print the entire server's reply to a custom window | <syntaxhighlight lang="mirc">;Print the entire server's reply to a custom window | ||
Line 247: | Line 241: | ||
window -deC @ $+ $sockname -1 -1 700 700 | window -deC @ $+ $sockname -1 -1 700 700 | ||
var %read | var %read | ||
− | sockread | + | sockread %read |
aline -p @ $+ $sockname : $+ %read | aline -p @ $+ $sockname : $+ %read | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
Line 267: | Line 261: | ||
=== Error Handling === | === Error Handling === | ||
− | Errors happen! It's a fact of life. It is your responsibility to check for them and gracefully handle them! The $sockerr identifier must be checked after every | + | Errors happen! It's a fact of life. It is your responsibility to check for them and gracefully handle them! The $sockerr identifier must be checked during every on sockread event and after every /sockread command. If the value of $sockerr is greater than zero, an error has occurred and we MUST stop whatever it is we were going to do with the socket, cleanup, perhaps display an error message and leave the on sockread event. |
− | |||
A basic example would look like this: | A basic example would look like this: | ||
Line 310: | Line 303: | ||
: <p>This webpage is dedicated for the socket tutorial purpose. </p> | : <p>This webpage is dedicated for the socket tutorial purpose. </p> | ||
: </div> | : </div> | ||
− | : <p>Your random color is: Pink</p> | + | : <p align="center">Your random color is: Pink</p> |
: </body> | : </body> | ||
: </html> | : </html> | ||
Line 325: | Line 318: | ||
tokenize 32 %read | tokenize 32 %read | ||
; get the color and remove the html tab | ; get the color and remove the html tab | ||
− | echo $color(info) -a Random Color: $noHTML($ | + | echo $color(info) -a Random Color: $noHTML($6) |
; close the socket, it's not needed | ; close the socket, it's not needed | ||
sockclose $sockname | sockclose $sockname | ||
Line 346: | Line 339: | ||
sockread %x | sockread %x | ||
; make sure it's a number | ; make sure it's a number | ||
− | + | if ($regex(%x,/^ *([\d,]+)$/)) { | |
− | if ($regex(%x,/ | + | ; parse the view count |
− | set %view. $+ $sockname | + | set %view. $+ $sockname $regml(1) |
} | } | ||
} | } | ||
− | + | else if (*Uploaded by* iswm %x) { | |
− | else if ( | ||
; print out the info | ; print out the info | ||
echo -a Title: $($+(%, title., $sockname), 2) $& | echo -a Title: $($+(%, title., $sockname), 2) $& | ||
− | + | $noHTML(%x) Views: $($+(%, view., $sockname), 2) | |
; cleanup | ; cleanup | ||
unset %*. $+ $sockname | unset %*. $+ $sockname | ||
Line 373: | Line 365: | ||
'''Note:''' Only the remote end-port, not you, can trigger this event. | '''Note:''' Only the remote end-port, not you, can trigger this event. | ||
− | [[Category:mIRC | + | [[Category:mIRC]] |