なでしこ > Delphi > 戻る

サーバーとの接続

 適当なサーバーに接続して何か情報をもらってきましょう。
■HTTPサーバーに接続して遊んでみる
■ユニットにまとめる

HTTPサーバーに接続して遊んでみる

 WinSockをちょっと試してみたところで、今度はサーバーに接続してとりあえず何か通信してみましょう。

 ちょっと長いのですが、以下のプログラムは、googleのサーバーに接続してインデックスページを取得してくるだけのプログラムです。

program connect;
{$APPTYPE CONSOLE}
uses
  Windows, SysUtils, WinSock;

var
  WSAData: TWSAData;
  phe: PHostEnt;
  s: TSocket;
  sockadd: sockaddr_in;
  buf: string;
  cnt: Integer;
begin
  // WinSock 初期化
  WSAStartup($0101, WSAData);
  //---------------------------
  // ソケットを作成 ... (1)
  s := socket(PF_INET, SOCK_STREAM, 0);
  if(s = INVALID_SOCKET)then
    raise Exception.Create('ソケットを作成できませんでした。');

  //---------------------------
  // ホスト情報を得る
  phe := gethostbyname('www.google.com');
  if phe = nil then raise Exception.Create('ホストがみつかりません。');

  // 接続先アドレスを設定 ... (2)
  ZeroMemory(@sockadd, Sizeof(sockadd));
  sockadd.sin_family := AF_INET;
  sockadd.sin_port   := htons(80);
  sockadd.sin_addr   := PInAddr(phe.h_addr_list^)^;

  //---------------------------
  // 接続
  if WinSock.connect(s, sockadd, sizeof(sockadd)) <> 0 then
    raise Exception.Create('接続できませんでした。');

  SetLength(buf, 1024 * 8); // 8Kのバッファ

  //---------------------------
  // 送信 ...(3)
  StrCopy(@buf[1], 'GET ./ HTTP/1.0'#13#10#13#10);
  send(s, PChar(buf)^, StrLen(@buf[1]), 0);

  //---------------------------
  // 受信 ...(4)
  while True do
  begin
    ZeroMemory(PChar(buf), Length(buf)); // メモリの初期化

    cnt := WinSock.recv(s, buf[1], Length(buf)-1, 0);

    if cnt = 0 then Break;
    if cnt = SOCKET_ERROR then
    begin
      cnt := WSAGetLastError;
      writeln('受信エラー=', cnt); Break;
    end;

    Writeln(string(PChar(buf))); // 受信したデータを画面に表示
    if Length(buf) > cnt then Break; // データを読みきった
  end;

  //---------------------------
  // 切断...(5)
  if (shutdown(s, SD_BOTH) <> 0) then writeln('シャットダウンに失敗');
  closesocket(s);
  WSACleanup;

  readln;

end.

前回もやったように、とりあえず、WSAStartupでWinSockを初期化します。それから、サーバーに接続するためには、まず、ソケットを作る必要があります。

そのため、プログラム中の(1)では、socketでソケットを作成します。そして、次にサーバーへ接続するのですが、接続のための connect 関数の引数の第二引数でsockaddr_inが必要になります。これは、(2)で設定しているのですが、前回やった、gethostbynameでIPアドレスを取得したもの、ポート番号、アドレスの種類を設定します。

接続ができたらあとは、待ちに待った送信です。送信は(3)のsend です。ここでは、GETコマンドをサーバーに送信します。この辺りは、HTTPプロトコルの話になるので、『"HTTPコマンド" GET』などのキーワードで検索するといろいろ出てきます。

受信処理が(4)なんですが、受信したデータが、バッファに入りきらないことがあるので、受信サイズが0になるまで繰り返し、受信を行います。

最後(5)では、接続を切断して終了です。

たかだか、サーバーに接続してインデックスページを得るだけなのに、ものすごくたくさんプログラムを記述しなくてはならず、骨が折れますね。

ユニットにまとめる

 TCP/IPクライアントが簡単に作れるユニットを作ってしまいましょう。

 では、全てをまとめあげた成果を見ていただきましょう。

program clientTest;
{$APPTYPE CONSOLE}
uses
  WSockUtils;
var
  client: TTcpClient;
  s: string;
begin
  client := TTcpClient.Create; // クラスの生成
  try
    client.connect('www.google.com', 80); // 接続
    client.send('GET ./ HTTP/1.0'#13#10#13#10); // コマンドの送信
    writeln(client.recvAll); // データの受信
  finally
    client.Free; // クラスの破棄
  end;
  readln; // 待機
end.

肝心のまとめたユニットは以下よりダウンロードしてください。内容は上のプログラムをただユニットに移し変えただけのしろものなので、敢えてプログラムを示すことはしません。

→googleのインデックスページ取得(ユニット版)



→トップへ →目次へ