GO BACK

REALbasic教室 その7


「インターネット接続の基本」


■ソケットとインターネットの仕組み


 その昔、「プログラムを組みたい!」と思う人の多くは、「ゲームを作りたい」という人だったように思います。とりあえず作ってみんなに楽しんでもらえるものといったら、ゲームが一番手っ取り早かったからですね。

 その後、ユーティリティのブームのようなものがあり、機能拡張ファイルやコントロールパネルを作りたいという人がかなり多くなってきました。そして今はといえば、やはり「インターネットを利用したプログラムを作りたい!」というのがトレンド(?)になっているように思います。そこで今回は、REALbasicでインターネットに接続する方法について説明していきましょう。

 REALbasicには、インターネット接続のために「ソケット(Socket)」という部品が用意されています。これはインターネットを使って様々なデータをやり取りするための部品です。

 インターネットというネットワークは、いくつもの階層からなる壮大なネットワークです。インターネットではさまざまなマシン、さまざまなOS、さまざまなアプリケーションが全て同じネットワーク上につながっています。こうしたことを可能にするため、インターネットはいくつもの階層ごとに細かなプロトコルが決められているのです。

 最も下層にあるのは「物理層(ハードウェア)」というもので、その上にネットワークインターフェイスについての取り決めがあり、更に上にインターネットプロトコル(IP)の取り決めがあり、更に上にトラスポートに関する取り決め(TCPとかUDPというもの)があり、そのまた更に上にWebブラウザやメールソフトなどのアプリケーションでデータをやり取りする取り決めがある、という感じになっています。

 REALbasicのソケットは、一番上のアプリケーションで利用する取り決め(アプリケーション層という)部分を利用するものです。つまり、既にマシンがインターネットに接続できる状態になっているとして、そこでメールソフトやブラウザのようなソフトを作りたいと思ったときに利用するものと考えるとよいでしょう。

 さて、このインターネットのアプリケーション層というのも、なかなかにややこしいものです。インターネットでは、さまざまなアプリケーションのデータがやり取りされていますから、それをきちんと仕分けし、「今送られてきたデータがどういう種類のモノか」をきちんと理解できるようになっていないといけません。

 そこで、インターネットの世界では、アプリケーションごとに「ポート番号」というものを割り振ることにしました。これは、いわば「プログラムのアドレス」です。インターネットの世界では、接続されたマシンごとにIPアドレスというものを割り振っていましたね。「200.81.50.1」というような番号のことです。これでマシンを識別していました。

 同様に、「送られたデータが、マシン上で動いているどのプログラムとやり取りするためのものか」を識別するために用意されているのがポート番号というものです。これはアプリケーションで使用しているプロトコル(データをやり取りする方法)ごとに番号が決まっています。主なものをまとめると、以下のようになるでしょう。


 21番 FTP(ファイルの転送用プロトコル)
 25番 SMTP(メール送信用のプロトコル)
 80番 HTTP(WWWなどハイパーテキスト用プロトコル)
 110番 POP3(メール受信用プロトコル)
 119番 NNTP(ニュースグループ用プロトコル)


 ソケットには、「Address」と「Port」というプロパティがあります。Addressは送信先のサーバーのアドレスで、Portが上記のポート番号です。この2つを設定することで、指定のインターネット上のサーバーにデータを送受することができるようになるのです。

 ――例えば、「http://www.h5.dion.ne.jp/~tuyano/」というホームページにあるデータを取り出そう、という場合を考えてみましょう(これは私のホームページです)。このURLは、3つの部分からなります。最初の「http://」というのは、「これはHTTPというプロトコルですよ」という意味ですね。従って、ポート番号は「80」になります。そして「www.netjoy.ne.jp」がサーバー名(Addressプロパティ)となります。そしてその後の「/~tuya/」は、サーバー内のディレクトリとなります。

 また、「tuyano@mac.com宛てにメールを出そう」と思ったとしましょう。この場合、単純なメールならばSMTPプロトコルを使います。ですからポート番号は「25」です。そしてサーバー名は「netjoy.ne.jp」になります(註:本当はmail.netjoy.ne.jpなのですが、このようにメールアドレスでmailサーバーの指定がない場合は、多くはちゃんと代理で受け取ってくれるようになっています。ただし絶対ではありません)。

 サーバーのアドレスとポート番号、この2つがインターネットアクセスをする際のもっとも重要なものなのです。



■ソケットの接続とデータのやり取り


 では、ソケットを使って指定のサーバーに接続するにはどうすればいいのでしょうか。――これには、以下のような手順を踏むことになります。


1.まず、ソケットのConnectメソッドを実行して接続を開始する。
2.ソケットのWriteメソッドを使ってアクセスのためのコマンドを送信する。
3.接続ができたら、Writeメソッドでデータを送信したり、ReadAllメソッドでデータをサーバから受信したりしてデータのやり取りを行なう。
4.全ての作業が終わったら、ソケットのCloseメソッドを実行して接続を切る。


 こんな感じです。なんだかファイルアクセスに似ていますね。まずConnectで接続し、WriteやReadAllで送受をし、最後にCloseする。これで完了です。

 見ればわかりますが、インターネットでのデータ送受は、指定のプロトコルに用意された各種のコマンドを送信して行ないます。ですから、何かのプログラムを作りたい場合は、まずこの「プロトコルのコマンド」を理解しなければいけません。

 また、コマンド実行後のデータ送受の方法も知っておく必要があるでしょう。――データの送信は、ただ送るだけですからボタンなどにプログラムを書いておけばいいでしょう。また、ソケットには接続が確定したときに呼び出されるConnectedというイベントが用意されていますから、ここに必要な送信コマンドなどを用意しておくのもよいでしょう。

 データの受信はそれだけではうまくいきません。データを転送してもらうコマンドを実行したら、後はどんどんサーバーからデータが送られてきてしまいます。これをどうやって受け取ればいいでしょう。

 こうした「送られてきたデータの受け取り」は、DataAvailableというイベントを使います。これはソケットに用意されているもので、データが送られてくると実行されるものです。ですからデータを受け取るプログラムを作る場合は、ボタンなどに接続してデータを送信するコマンドなどを送るコードを用意しておき、DataAvailableに実際にデータが送られてきたときの処理を書いておく、ということになります。

 また、この他にErrorというイベントも用意されています。これはサーバーとのやり取りにエラーが発生したときに呼び出されるものです。インターネットでのデータやり取りは、エラーの発生がつきものですから、その処理は用意しておくべきでしょう。



■メール送信プログラムを作る


 ソケットの使い方は、実際にプログラムを作ってみないと実感がわかないことでしょう。では、簡単な例として、SMTPプロトコルを使って簡単なメール送信ソフトを作ってみましょう。

1.まずは、必要な部品の配置から。最初にEditFieldを4つ作成する。それぞれの名前は以下のように設定すること。
 1つ目:SendField
 2つ目:MyField
 3つ目:SubjectField
 4つ目:DataField

 1〜3はそれぞれ送信先のメールアドレス、送信者のメールアドレス、タイトルを入力するためのものなので、1行だけの大きさでいい。4つ目は、メールの内容を書き込むためのものなので、大きめに配置し、MultipleLineとScrollBarプロパティをそれぞれONにして複数行が入力可能にしておくこと。

2.次にSocketを1つ作成する。名前はデフォルトの「Socket1」のままでいい。そしてPortプロパティを「25」に設定する。

3.CommandButtonを1つ作成する。これは名前を「Access」とする。またCaptionを「送信」としておく。これがメールを送信するボタンとなる。

 全て作成したら、最後にソースコードを記述します。ソースコードは全部で3箇所に記述するので間違えないようにしてください。

●AccessボタンのActionイベント●
Sub Action()
  dim Num as Integer
  
  Num = InStr(SendField.Text,"@")
  Socket1.Address = Mid(SendField.Text,Num+1)
  
  Access.Caption = "送信中..."
  Socket1.Connect
End Sub

●Socket1のConnectedイベント●
Sub Connected()
  dim crlf as string
  dim result as String
  dim Num as Integer
  
  crlf = chr(13) + chr(10)
  
  Socket1.write "HELO "+Socket1.Address +crlf
  result = Socket1.readAll
  Socket1.write "MAIL FROM:"+MyField.Text+crlf
  result = Socket1.readAll
  Socket1.write "RCPT TO:"+SendField.Text+crlf
  result = Socket1.readAll
  Socket1.write "DATA"+crlf
  result = Socket1.readAll
  Socket1.write "SUBJECT: "+SubjectField.Text+crlf+crlf
  result = Socket1.readAll
  Socket1.write DataField.Text+crlf+"."+crlf
  result = Socket1.readAll
  Socket1.write "QUIT"+crlf
  result = Socket1.readAll
  Access.Caption = "送信"
  Socket1.Close
  MsgBox "送信しました。"
End Sub

●Socket1のErrorイベント●
Sub Error()
  BEEP
  MsgBox "エラーが起きました。"
  Access.Caption = "送信"
  Socket1.Close
End Sub

 これで完成です。わかりやすくするために、それぞれのEditFieldにラベルを使って題名をつけておくなどするとよいでしょう。

 では、実際にこれを実行してみましょう。インターネットに接続していることを確認し、SendFieldに相手先のアドレスを(とりあえず自分のメールアドレスを書いて下さい)、MyFieldに自分のメールアドレス、そしてSubjectFieldには「Test」とでも書いておきましょう。そしてDataFieldに適当にテキストを書き込み、「送信」ボタンを押します。すぐに画面に「送信しました。」というメッセージが表示されることでしょう。

 無事送信できたら、しばらくしてメールソフトを使ってメールをチェックしてみて下さい。無事、送信したメールが届いていれば実験成功です!



■SMTP送信の仕組み


 では、実際に作成したソースコードをチェックしてみましょう。まずは、送信ボタンのコードからです。

Num = InStr(SendField.Text,"@")
Socket1.Address = Mid(SendField.Text,Num+1)
ここでは、送信者のメールアドレスから送信先のサーバー名を取り出しています。InStrというのは、ある文字が別の文字列の何文字目にあるかを返す関数。ここで@のある位置を調べています。そして、その次のMid関数で、SendField.Textの文字列の@のある位置の次の文字から最後までを取り出してAddressに設定しています。

 メールアドレスというのは「ABC@ABCNET.co.jp」というような形になっています。この@より後の「ABCNET.co.jp」というのが、サーバー名になるわけです。そこで@の位置を調べ、その位置より後の文字列を取り出してAddressにしているというわけです。

(※註――ただし、これがインターネットにおけるサーバー名取得の正しい方法だ、とは思わないで下さい。ここでは、とりあえず「メールアドレスからこんな感じで簡単に取り出してもだいたいはうまくいくよ」ということで、このようなやり方をしているだけです。これではうまくいかない場合ももちろんあります)


Access.Caption = "送信中..."
Socket1.Connect

そして、ボタンの表示を「送信中...」と変えて、Socket1をConnectしています。これで接続のコードは完了です。

 次は、接続完了してからの動作を記述しているConnectedイベントの部分です。これはちょっとややこしそうですね。


crlf = chr(13) + chr(10)

まず「crlf」という変数に何か変なものをおさめています。このchrというのは、指定したASCIIコードのキャラクタを返す関数です。13番はキャリッジリターンというもので、10番はラインフィードというものです。

 これは、インターネットでコマンドを送るとき、最後に「ここが命令の終わりだよ」という意味で送る決まりのキャラクタだと思って下さい。これを送信すると、サーバーは「コマンドはここで終わりだな」と認識します。多用するものなので、変数におさめて使いやすくしているのですね。

Socket1.write "HELO "+Socket1.Address +crlf
result = Socket1.readAll

さて、最初に送るのは「HELO 《サーバー名》」というコマンドです。これで指定のメールサーバーにメールの送信をお願いします。Writeメソッドというのは、ソケットを使ってコマンドやデータを送信するためのメソッドです。このように文字列としてコマンドを送信し、最後にコマンド終了を示すキャリッジリターン+ラインフィード記号を送ります。

 コマンドを送信すると、必ずサーバーから返事が返ってきます。次行の「readAll」というのは、サーバーから送り返されてきたデータを全て読み込むメソッドです。この送り返された返事をチェックすれば、エラーが起きたかどうか、きちんとサーバーが受け取っているのかわかるわけです。ここではとりあえず細かなエラー処理は省略しています。


Socket1.write "MAIL FROM:"+MyField.Text+crlf
result = Socket1.readAll
Socket1.write "RCPT TO:"+SendField.Text+crlf
result = Socket1.readAll

次に「MAIL FROM:《送信者のメールアドレス》」というコマンドを送っています。そして返事を確認してから、「RCPT TO:《送り先のメールアドレス》」というコマンドを送ります。この2つはSMTPでメールを送るときには必須のコマンドです。


Socket1.write "DATA"+crlf
result = Socket1.readAll

次に「DATA」というコマンドを送っていますね。これは「ここまではヘッダーで、ここからがボディになるよ」という信号です。ヘッダーというのは、サーバーがデータを処理するのに必要な情報がおさめてある部分です。そしてボディというのが、実際に送信されるデータそのものなのです。


Socket1.write "SUBJECT: "+SubjectField.Text+crlf+crlf
result = Socket1.readAll

ボディには、すぐにメールの内容がくるとは限りません。「インターネットヘッダー」といって、独自のフィールドで細かな情報をボディに持たせることができるのです。ここでは「SUBJECT:《題名》」というコマンドを送って、メールのタイトルを設定しています。

 よくみると、最後にcrlfを2つ送っていますね。これは、「インターネットヘッダーはこれで終わりで、次からメールの内容だよ」ということを示しています。インターネットヘッダーを複数設定するときもあるでしょうから、そういう場合はコマンドの終わりにcrlfを1つ入れ、一番最後のコマンドの時だけ2つ入れればよいわけですね。


Socket1.write DataField.Text+crlf+"."+crlf
result = Socket1.readAll

さて、ここがメールの本体です。メールの本体の終了はcrlf+ピリオド+crlfです。これを最後に送信すると、「これでデータは全て終わりだな」と判断します。


Socket1.write "QUIT"+crlf
result = Socket1.readAll
Access.Caption = "送信"
Socket1.Close
MsgBox "送信しました。"

全て終わったら、最後に「QUIT」というコマンドを送ります。これはサーバーに作業終了を知らせるコマンドです。そしてソケットをCloseして接続を切り、メッセージを表示しています。

 注意して欲しいのは、「Closeでインターネットとの接続が切れるわけではない」ということです。これは、あくまで指定のサーバーとの接続を終わりにするためのものであって、インターネットそのものは切られません。



■HTTPプロトコルを使う


 ついでといっては何ですが、WebでおなじみのHTTPプロトコルも使ってみましょう。これは某雑誌連載向けに作った簡単なプログラムで、指定したWebサイトのHTMLドキュメントをダウンロードするためのものです。

 まずWindow1を開いて、以下の部品を作成して下さい。


●EditField(3つ)
Name:Host, dir, DataField
Hostとdirはサーバー名とディレクトリを入力するフィールド。DataFieldは取り込んだデータを表示するものなので大きく配置。


●CommandButton(1つ)
Name:Access
接続用ボタン。


●Socket(1つ)
Port:80
アドレスは空白のままでいい。

 できあがったら、次はプログラムの作成です。以下のソースコードを、指定のサブルーチンにそれぞれ記入して下さい。

●AccessのAction●
Sub Action()
  dim crlf as string
  dim Path as String
  dim url as String
  
  crlf = chr(13) + chr(10)
  DataField.Text = ""
  Path = dir.Text
  url = Host.Text
  
  Socket1.address = url
  Socket1.connect
  Socket1.write "GET " + Path + " HTTP/1.0"+crlf
  Socket1.write "Host: "+ url +crlf
  Socket1.write crlf
End Sub

●Socket1のConnected●
Sub Connected()
  Access.Caption = "Loading..."
End Sub

●Socket1のDataAvailable●
Sub DataAvailable()
  Dim ReadData as String
  ReadData = Socket1.ReadAll
  DataField.Text = DataField.Text + ReadData
End Sub

●Socket1のError●
Sub Error()
  Access.Caption = "Access"
  Socket1.Close
End Sub

 以上で完成です。――これは、サーバー名とディレクトリを入力してボタンを押すと、そのHTMLドキュメントをダウンロードしてDataFieldに表示するというものです。

 例えば「http://www.h5.dion.ne.jp/~tuyano/index.html」というファイルをダウンロードしようと考えたとします。この場合、先に触れましたがこのURLは3つの部分からなります。「www.netjoy.ne.jp」というのがサーバー名で、「/~tuya/index.html」がディレクトリ名となるわけですね。

 これをそれぞれ入力してボタンを押せば、ちゃんと私のホームページのHTMLテキストが書き出される、というわけです。試してみましょう。

 ここでは、HTTPプロトコルで以下のようなテキストをサーバーに送っています。


GET 《ディレクトリ》 HTTP/1.0
Host: 《サーバー》


 これが指定したファイルを転送するためのHTTPの命令です。後は送られてきたデータを受け取るプログラムがDataAvailableサブルーチンに用意してあります。詳細は説明しませんので、それぞれでコードを解析してみて下さい。


◆    ◆    ◆


 というわけで、ざっとSMTPとHTTPプロトコルを使ったインターネットアクセスの基本について説明しました。ソケットを使えば、インターネット利用のアプリケーションが作れることはこれでわかったことでしょう。しかし同時に、単にソケットの使い方がわかっただけではプログラムは作れないこともわかったのではないでしょうか。

 インターネットアプリケーションを作るためには、何より利用するプロトコルについて精通しなければいけません。ここでは最も簡単なSMTPとHTTPを使いましたが、それでも必要なコマンドの使い方、その手順などをしっかり覚えなければいけないことがわかったはずです。

 ソケットは非常に簡単ですが、インターネット自体をよく知らなければこれより先は進めないのです。そのことをよく理解し、まずはインターネットの勉強をするようにしてください。


GO NEXT


GO HOME