ネットワーク VB6
前へ 目次へ 次へ 

複数のクライアントからの接続要求を受け付ける

 サーバのプログラムでWinsockコントロールは1つの接続要求しか受け付けない。複数の接続要求を受け付けるには、必要な数のコントロールが必要になるので、コントロール配列としてWinsockを用意する。


サーバーの処理

 フォームにWinsockコントロールを1つ配置し、Indexプロパティを0に設定してコントロール配列とする。0番のWinsock(実際にはWinsock1(0))で接続要求を受け付け、接続要求があれば、新規のWinsock(Winsock1(1)、1番目)を作成してこれと接続する。
 次に、別の接続要求があれば、新規のWinsock(Winsock1(2)、2番目)を作成してこれと接続する。以降、同じように接続要求があれば、新規のWinsockと接続していく。したがって、0番目のWinsockは接続要求の受付だけを担当することになる。


フォームの準備

 新規フォームを用意し、プロパティを次のように設定する。

 Caption … サーバ、   Height … 3600、   Width … 4800

 フォームに次のようなコントロールを配置する。

 リスクボックス(List1)
  List … 接続先、  Height … 2400、  Left … 120、  Top … 120、  Width … 4455

 コマンドボタン(Command1)
  Caption … 終 了、  Height … 375、  Left … 3480、  Top … 2640、  Width … 1095

 Winsock(Winsock1)
  Index … 0
  実行時には表示されないので適当な位置に配置する。大きさは固定である(サイズ変更できない)。

・プログラムリスト

 グローバル変数

Option Explicit        '変数宣言を強制する
Dim Word(1, 20) As String      '単語登録用
Dim WsockNum As Integer        'Winsockコントロール配列用
Dim CompName(20) As String    'リモートコンピュータ名用

 グローバル変数として、前と同じように配列Wordは英単語と日本語訳の登録用として、変数WscokNumはコントロール配列Winsock1の添字用として、配列CompNameは接続要求のあった(リモート)コンピュータ名登録用として、それぞれ(General) (Declarations)にプログラムを書く。とりあえず配列CompNameは21個用意してある。ケースによって増減すると良い。

 初期設定

Private Sub Form_Load()
    WsockNum = 0        'コントロール配列の添字(0番目)
    Winsock1(0).LocalPort = 1001    '接続用ポート番号設定
    Winsock1(0).Listen            '接続要求受付
    '単語の登録
    Word(0, 0) = "english"
    Word(1, 0) = "英語"
    Word(0, 1) = "apple"
    Word(1, 1) = "リンゴ"
    Word(0, 2) = "japan"
    Word(1, 2) = "日本"
    Word(0, 3) = "computer"
    Word(1, 3) = "コンピュータ"
    Word(0, 4) = "sun"
    Word(1, 4) = "太陽"
    Word(0, 5) = "moon"
    Word(1, 5) = "月"
End Sub

 最初に実行されるForm_Loadプロシージャでコントロール配列Winsock1の添字用変数WsockNumを0で初期化する。次に、Winsoc1(0)の接続要求受付用のポート番号を設定し、接続要求を待つ。
 さらに、前と同じように単語を登録する。word(0,n)には英単語、word(1,n)には日本語訳を登録する。上のプログラムでは、6個だけ登録している。

 接続要求の受付

Private Sub Winsock1_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    'コントロール配列0で接続要求あり
    '0番目のWinsockは接続要求受け付け用で、実際に接続には使用しない。
    If Index = 0 Then
        WsockNum = WsockNum + 1    '添字を加算
        '新規にWinsockを追加する
        Load Winsock1(WsockNum)
        '新規追加したWinsockのポート番号設定(0とする)
        Winsock1(WsockNum).LocalPort = 0
        '新規追加したWinsockで接続処理をする
        Winsock1(WsockNum).Accept requestID
    End If
End Sub

 複数のクライアントからの接続要求を受け付けるので、Winsoc1が配列になっているだけで、ほとんど前(1対1の接続)と同じである。
 念のため、接続要求を受けたWinsock1が0番目であることを確認している(If Index = 0 Then)。
 コントロール配列Winsock1の添字用変数WsockNumに1を加算して、新しくWinsock1を追加する。追加には、Load命令を使う。
 追加したWinsock1のポート番号を0に設定する。ポート番号を0にすると任意のポート番号が使われる(ポート番号はコンピュータが決めてくれる)。
 追加したWinsock1と接続要求のあったコンピュータとの接続処理をし、接続を完了する。

 データ受信時の処理

Private Sub Winsock1_DataArrival(Index As Integer, ByVal bytesTotal As Long)
    '引数Index番目のWinsockからデータを受信
    Dim dat As String, ans As String    'データ受信用、送信用
    Dim n As Integer

    Winsock1(Index).GetData dat    'データ受信
    'クライアントのコンピュータ名受信
    If Left(dat, 2) = "##" Then
        CompName(Index) = Mid(dat, 3)        'コンピュータ名登録
        List1.AddItem CompName(Index), Index    'List1に登録
        Exit Sub        'プロシージャを抜け出す
    End If
    'リストに受信データ表示
    List1.RemoveItem Index    'リストから削除
    List1.AddItem CompName(Index) & "=" & dat, Index    'リストにデータ追加
    For n = 0 To 20
        If dat = Word(0, n) Then
            Winsock1(Index).SendData Word(1, n)
            Exit For
        End If
    Next n
    If n = 21 Then
        Winsock1(Index).SendData "わかりません"
    End If
End Sub

 リストボックス(List1)は、コンボボックス(リッチテキスト試作 Vフォントの設定 参照)のリスト部分だけのコントロールである。データの追加にはAddItemメソッド、データの削除にはRemoveItemメソッドを使う。
 ここでは、データの追加で

List1.AddItem コンピュータ名, 番号

の形で使っている。これは、コンピュータ名を指定した番号の位置(リストの行番号と考えればよい。0から始まる。)に追加することを表している。

 クライアントが接続を閉じたときの処理

Private Sub Winsock1_Close(Index As Integer)
    CompName(Index) = ""    'コンピュータ名削除(消去)
    List1.RemoveItem Index    'リストからも削除
    List1.AddItem "", Index    '空白を挿入
    Winsock1(Index).Close    '接続を閉じる
End Sub

 クライアントが接続を閉じるとサーバのCloseプロシージャが呼び出される。閉じられたクライアントとの接続は引数のIndex番目で行われていたので、配列CompName(Index)を空白に(コンピュータ名を削除)する。
 リストに表示されているデータを変更するメソッドはないので、リストのIndex番目を削除してから改めてIndex番目に空白を追加している。
 最後に、接続を閉じている。

 サーバの終了処理

Private Sub Command1_Click()
    Dim x As Integer

    For x = 0 To WsockNum
        Winsock1(x).Close
    Next x
    Unload Me
    End
End Sub

 追加したWinsockすべてを削除(閉じる)する。閉じるのは0番からWsockNum番までである。


クライアントの処理

 クライアントのプログラムは、前の1対1の接続で作成したものがそのまま使えるので、ここでは省略する。


実行する

 複数のクライアントから接続要求を受け付けるプログラムなので、複数のクライアントが必要になる。クライアントの数だけVisualBasicを起動することもできないので、コンパイルして実行ファイルを作成してから実行する。


【課題】エラー処理を入れていないので、実行中に停止するかもしれない。Winsock関係でエラーが発生するとErrorプロシージャが呼び出される(詳しくは、ヘルプを参照のこと)ので、エラー処理も考えてみよう。


前へ 目次へ 次へ 
Copyright © 2001 Hiroshi Masuda 

 

 

inserted by FC2 system