winsockを使って通信を行うには?


えぷと  URL  2002-02-15 10:22:16  No: 576  IP: [192.*.*.*]

delphiは先週から触り始めた素人です。
win2k + delphi6 personal を使用しています。
internetの中のserversocketとclientsocketを使用して通信を行いたいのですが記述方法がまったくわかりません。
イベントのOnConnect や OnWriteなどを使ってみようとしていますが同様に全然わかりません。
複数人が入れるチャットのプログラムを作成したいと思っています。

編集 削除
にしの  2002-02-17 14:00:37  No: 577  IP: [192.*.*.*]

Delphi本を購入された方がよいと思います。
servesocket, clientsocketのイベントの記述がわからないだけなら、掲示板でちょっと聞けばわかるかもしれませんが、通信の仕様がわからないのなら、掲示板で聞くには量が多すぎます。

Delphi6 Personalには、サンプルは入っていませんか。
Delphi5のヘルプを見ると、chatのサンプルが入っていると書いてありますが。

TServerSocketは、Openすれば接続されるまで待機していますから、WinSockを直に使って、bind,listenなどの面倒な手続きは必要ないです。
Activeの切り替えで、勝手にOpenしてくれますし。
TClientSocketも同じです。Hostプロパティにサーバのアドレスを指定して、Openするだけです(Active:=FalseしてActive:=Trueでも同じ)。
イベントは、適当にTMemoなどにイベントが起きたことを書いていけば、だいたい想像がつくと思います。
# サーバのOnClientReadが、クライアントからサーバにデータが投げられたときのイベントなど
接続さえ出来れば、
ClientSocketの、Socketプロパティを使ってデータを送信
ClientSocket1.Socket.SendText('データ');
OnClientReadイベントの引数、Socketを使ってデータ受信
Socket.ReceiveText
で出来ます。
相手のIPなどは、Socket.Remoteなんたら、というプロパティで取得できます。

Soketを使用したアプリケーションを作成したことがなく、ちょっと使ってみた感じではそうでした。
間違っている部分があるかもしれません。

編集 削除
相乗りくん  2002-02-19 02:28:19  No: 578  IP: [192.*.*.*]

D6 Personalには、Chatサンプルが付いてないですね。(T_T)
で、BorlandサイトにあるC++Builder用のChatサンプルを Delphi用に書き換えてみました。
これは1対1のChat用なので、多人数用にするにはサーバーとなるパソコン側で参加者を管理しないとダメなんですよね?
サーバー側は、参加人数分のServerSocketコンポーネントを用意する必要があるんでしょうか?

//--------------------------------------------
procedure TForm1.ListenItemClick(Sender: TObject);
begin
  ListenItem.Checked := not ListenItem.Checked;
  if (ListenItem.Checked) then begin
    ClientSocket1.Active := False;
    ServerSocket1.Active := True;
    Show_BarInfo('Listening...');
  end else begin
    if (ServerSocket1.Active) then begin
      ServerSocket1.Active := False;
    end;
    Show_BarInfo('');
  end;
end;
//--------------------------------------------
procedure TForm1.ConnectItemClick(Sender: TObject);
begin
  if (ClientSocket1.Active) then ClientSocket1.Active := False;

  if (InputQuery('Connect to', 'Address Name:', Server)) then begin
    if (Length(Server) > 0) then begin
      ClientSocket1.Host := Server;
      ClientSocket1.Active := True;
    end;
  end;
end;
//--------------------------------------------
procedure TForm1.DisconnectItemClick(Sender: TObject);
begin
  ClientSocket1.Close;
  ListenItemClick(Sender);
end;
//--------------------------------------------
procedure TForm1.ExitItemClick(Sender: TObject);
begin
  ServerSocket1.Close;
  ClientSocket1.Close;
  Close;
end;
//--------------------------------------------
procedure TForm1.MemoSendKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_RETURN) then begin
    if (IsServer) then begin
      ServerSocket1.Socket.Connections[0].SendText(MemoSend.Lines[MemoSend.Lines.Count - 1]);
    end else begin
      ClientSocket1.Socket.SendText(MemoSend.Lines[MemoSend.Lines.Count - 1]);
    end;
  end;
end;
//--------------------------------------------
procedure TForm1.Show_BarInfo(const msg: string);
begin
  StatusBar1.SimpleText := msg;
end;
//--------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
  ListenItemClick(Sender);
end;
//--------------------------------------------
procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Show_BarInfo('Connected to: ' + Socket.RemoteHost);
end;
//--------------------------------------------
procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  ListenItemClick(Sender);
end;
//--------------------------------------------
procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  MemoRecv.Lines.Add(Socket.ReceiveText);
end;
//--------------------------------------------
procedure TForm1.ClientSocket1Error(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
  MemoRecv.Lines.Add('Error connecting to : ' + Server);
  ErrorCode := 0;
end;
//--------------------------------------------
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  MemoRecv.Lines.Add(Socket.ReceiveText);
end;
//--------------------------------------------
procedure TForm1.ServerSocket1Accept(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  IsServer := True;
  Show_BarInfo('Connected to: ' + Socket.RemoteAddress);
end;
//--------------------------------------------
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  MemoRecv.Lines.Clear;
end;
//--------------------------------------------
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  ServerSocket1.Active := False;
  ListenItem.Checked := not ListenItem.Checked;
  ListenItemClick(Sender);
end;
//--------------------------------------------

編集 削除
にしの  2002-02-19 09:39:43  No: 579  IP: [192.*.*.*]

多人数を管理するなら、TThreadを使用するといいかもしれません。
そこで、TServerSocketを生成していけばできそうな気がします。

編集 削除
相乗りくん  2002-02-23 03:15:22  No: 580  IP: [192.*.*.*]

少しづつ分かってきたのですが、TServerSocketは、面倒なThreadを使わずに stNonBrockingモードで複数のClientに対応できるんですね。
Socketプロパティのかわりに、Socket.Connectionsプロパティで個々のClientを区別してアクセス出来るようです。
でも、D6 Personalには TServerSocket、TClientSocketに関するヘルプが無いので、サーバーに接続しているCientの数を示すプロパティが存在するのか、Clientの数に制限があるのかなど、まだよく分からない部分も多くて…

TServerSocket、TClientSocketにどんな実行時プロパティ、メソッドがあるのか教えてもらえないでしょうか?

編集 削除
にしの  2002-02-23 08:40:41  No: 581  IP: [192.*.*.*]

Delphi5では、それぞれ実行時プロパティに
Socket: TServerWinSocket; // TServerSocket側
Socket: TClientWinSocket; // TClientSocket側
があります。
実行時メソッドは、Create,Destroyくらいしか見あたりません。TComponentの実行時メソッド・プロパティは使えると思います。

サーバに接続しているClientの数は、
TServerSocket.Socket.ActiveConnections
です。
TServerSocket.Socketに、
Connections[Index: integer]: TCustomWinSocket;
があり、これがTServerClientWinSocketのオブジェクトです。
つまり、
ServerSocket1.Socket.Connections[0]
から、
ServerSocket1.Socket.Connections[ActiveConnections - 1]
が、接続しているClientのオブジェクトです。
# ServerSocket1はTServerSocketのオブジェクト

クライアントの制限はないようです。プロパティには見あたりませんでした。
サーバー側が、クライアントの接続数を見て判断させるのだと思います。

編集 削除
Nak  2003-07-24 17:43:47  No: 582  IP: [192.*.*.*]

いまさらですが、英語版のヘルプがここにあります。
Socket関係のコンポーネントも記載されています。
ftp://ftp.borland.com/pub/delphi/techpubs/delphi5/d5vcl_s.zip

編集 削除
PoThi  2003-07-25 23:10:25  No: 583  IP: [192.*.*.*]

参考になるかどうかわかりませんが
http://www.asahi-net.or.jp/~nk2w-ishr/winsock0.htm

編集 削除
シュークリーム  2003-07-28 11:06:25  No: 584  IP: [192.*.*.*]

ちなみに...ですが
Delpi7では
そのコンポーネントサポートされていません。
削除されています。

つまり、Delphiのバージョンアップの可能性があるのなら
使用しないほうが良いと思いますが...

編集 削除
あもあも  2004-11-15 12:23:50  No: 585  IP: [192.*.*.*]

すみませんちょっと聞きたいんですが、
ServerSocketのOnClientReadが起こったときにどのクライアントから
データが送られてきたかっていうことはわからないんでしょうか?

ServerSocket1.Socket.Connections[0].Receivetext
                                ↑
ここの数字は簡単に得ることができないんでしょうか?

編集 削除