delphiは先週から触り始めた素人です。
win2k + delphi6 personal を使用しています。
internetの中のserversocketとclientsocketを使用して通信を行いたいのですが記述方法がまったくわかりません。
イベントのOnConnect や OnWriteなどを使ってみようとしていますが同様に全然わかりません。
複数人が入れるチャットのプログラムを作成したいと思っています。
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を使用したアプリケーションを作成したことがなく、ちょっと使ってみた感じではそうでした。
間違っている部分があるかもしれません。
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;
//--------------------------------------------
多人数を管理するなら、TThreadを使用するといいかもしれません。
そこで、TServerSocketを生成していけばできそうな気がします。
少しづつ分かってきたのですが、TServerSocketは、面倒なThreadを使わずに stNonBrockingモードで複数のClientに対応できるんですね。
Socketプロパティのかわりに、Socket.Connectionsプロパティで個々のClientを区別してアクセス出来るようです。
でも、D6 Personalには TServerSocket、TClientSocketに関するヘルプが無いので、サーバーに接続しているCientの数を示すプロパティが存在するのか、Clientの数に制限があるのかなど、まだよく分からない部分も多くて…
TServerSocket、TClientSocketにどんな実行時プロパティ、メソッドがあるのか教えてもらえないでしょうか?
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のオブジェクト
クライアントの制限はないようです。プロパティには見あたりませんでした。
サーバー側が、クライアントの接続数を見て判断させるのだと思います。
いまさらですが、英語版のヘルプがここにあります。
Socket関係のコンポーネントも記載されています。
ftp://ftp.borland.com/pub/delphi/techpubs/delphi5/d5vcl_s.zip
参考になるかどうかわかりませんが
http://www.asahi-net.or.jp/~nk2w-ishr/winsock0.htm
ちなみに...ですが
Delpi7では
そのコンポーネントサポートされていません。
削除されています。
つまり、Delphiのバージョンアップの可能性があるのなら
使用しないほうが良いと思いますが...
すみませんちょっと聞きたいんですが、
ServerSocketのOnClientReadが起こったときにどのクライアントから
データが送られてきたかっていうことはわからないんでしょうか?
ServerSocket1.Socket.Connections[0].Receivetext
↑
ここの数字は簡単に得ることができないんでしょうか?
ツイート | ![]() |