//--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- // 変数初期化 __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ClientSysCom[0] = "Host No:"; ClientSysCom[1] = "ClientMemberAnswer"; ClientSysCom[2] = "ServerDown"; ClientSysCom[3] = "DeleteHost No:"; ClientSysCom[4] = "AddHost:"; ServerSysCom[0] = "ClientMemberRequest"; ServerSysCom[1] = "ToClient"; ServerSysCom[2] = "ClientDisconnect"; Button1->Brush->Style = bsSolid; Button1->Brush->Color = clRed; Memo1->Text = ""; Memo2->Text = ""; Form1->Width = Panel2->Width + Panel4->Width+8; SpeedButton2->Down = true; Panel2->Visible = true; } //--------------------------------------------------------------------------- // 初期設定 void __fastcall TForm1::FormCreate(TObject *Sender) { AnsiString str; char chr; // services.txt から使用可能サービスリストを読み込む serv = new TFileStream("services.txt", fmOpenRead | fmShareDenyWrite); for(int i=0;serv->Size > serv->Position;) { str =""; serv->Read(&chr,1); while((chr != VK_RETURN) && (serv->Size > serv->Position)) { str.Insert(AnsiString(chr),str.Length()+1); serv->Read(&chr,1); } serv->Position++; // 改行は\r\nだから chr = *(str.SubString(1,1)).c_str(); if(chr >= 'A' && chr <='z' && str.SubString(23,3) == "tcp") { connect1[i].service = str.SubString(1,str.AnsiPos(" ")-1); connect1[i].port = StrToInt(str.SubString(17,5)); ComboBox1->Items->Add(connect1[i].service); i++; } } delete serv; // サービス名の並び替え Connect tmp; for(int i=0;iItems->Count;i++) { for(int j=i+1;jItems->Count;j++) { if(connect1[i].service.LowerCase() > connect1[j].service.LowerCase()) { tmp = connect1[i]; connect1[i] = connect1[j]; connect1[j] = tmp; ComboBox1->Items->Exchange(i,j); } } } } //--------------------------------------------------------------------------- // 接続先を書いた場合はIPは書く必要が無い void __fastcall TForm1::Edit2Change(TObject *Sender) { if(Edit2->Text == "") Edit1->Enabled = true; else Edit1->Enabled = false; } //--------------------------------------------------------------------------- void __fastcall TForm1::ComboBox1Change(TObject *Sender) { if(ComboBox1->ItemIndex >= 0) Edit3->Text = connect1[ComboBox1->ItemIndex].port; Edit3->Enabled = false; // 接続サービス欄が空白だったら接続ポートを記入できる if(ComboBox1->Text == "") Edit3->Enabled = true; } //--------------------------------------------------------------------------- // クライアント接続しようとした時のエラー void __fastcall TForm1::ClientSocket1Error(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode) { StatusBar1->Panels->Items[0]->Text = "not find server"; ErrorCode = 0; } //--------------------------------------------------------------------------- // 自分がクライアントの時サーバーに繋がったら void __fastcall TForm1::ClientSocket1Connect(TObject *Sender, TCustomWinSocket *Socket) { StatusBar1->Panels->Items[0]->Text = "connecting"; // クライアントのIPアドレスを表示 // refer winsock.h in_addr a = ClientSocket1->Socket->LookupName( ClientSocket1->Host); Edit1->Text = AnsiString(a.s_net)+"."+AnsiString(a.s_host)+ "."+AnsiString(a.s_lh)+"."+AnsiString(a.s_impno); } //--------------------------------------------------------------------------- // クライアントモード void __fastcall TForm1::Button3Click(TObject *Sender) { /* mciSendString("open cdaudio", NULL, 0, NULL); mciSendString("set cdaudio door open",NULL, 0, NULL); mciSendString("close cdaudio", NULL, 0, NULL); */ if(ServerSocket1->Active==true) return; ClientSocket1->Address = Edit1->Text; ClientSocket1->Host = Edit2->Text; ClientSocket1->Port = StrToIntDef(Edit3->Text,0); ClientSocket1->Service = ComboBox1->Text; ClientSocket1->Open(); } //--------------------------------------------------------------------------- // サーバーモード void __fastcall TForm1::Button4Click(TObject *Sender) { /* mciSendString("open cdaudio", NULL, 0, NULL); mciSendString("set cdaudio door open",NULL, 0, NULL); mciSendString("close cdaudio", NULL, 0, NULL); */ if(ClientSocket1->Active==true) return; ServerSocket1->Port = StrToIntDef(Edit3->Text,0); ServerSocket1->Service = ComboBox1->SelText; // 設定したポートが開いてない場合は開いてるポートを探す int f=0; while(f == 0) { f=1; try { ServerSocket1->Open(); } catch(...) { ServerSocket1->Service = ""; ServerSocket1->Port++; if (ServerSocket1->Port<1000) f = 0; else { ShowMessage("空いてるPortがありません"); return; } } } StatusBar1->Panels->Items[0]->Text = "Server Mode"; Button6->Visible = true; } //--------------------------------------------------------------------------- // サーバーの準備ができたら void __fastcall TForm1::ServerSocket1Listen(TObject *Sender, TCustomWinSocket *Socket) { // サーバーのIPアドレスを表示 // refer winsock.h in_addr a = ServerSocket1->Socket->LookupName( ServerSocket1->Socket->LocalHost); Edit1->Text = AnsiString(a.s_net)+"."+AnsiString(a.s_host)+ "."+AnsiString(a.s_lh)+"."+AnsiString(a.s_impno); // サーバーのホスト名を表示 Edit2->Text = ServerSocket1->Socket->LocalHost; } //--------------------------------------------------------------------------- // メッセージ送信 void __fastcall TForm1::Button2Click(TObject *Sender) { AnsiString str; str = Memo1->Text; if(ServerSocket1->Active) { // メッセージの先頭に発言者名を付け足す str = "server : \r\n"+str; // 送信先の相手全員にメッセージを送信 for(int i=0;iItems->Count;i++) { if(ListBox1->Selected[i]==true) ServerSocket1->Socket->Connections[i]->SendText( str); } } if(ClientSocket1->Active) { // メッセージの先頭に発言者のホスト名を付け足す str = ClientSocket1->Socket->LocalHost. SubString(1,5)+" : \r\n"+str; // 相手がこのソフト以外のサーバーだったら if(ListBox1->Items->Text=="") ClientSocket1->Socket->SendText(Memo1->Text); else { // 送信先がサーバーだったら if(ListBox1->Selected[0]==true) ClientSocket1->Socket->SendText(str); // 送信先の相手全員にメッセージを送信 for(int i=1;iItems->Count;i++) { // i番目のホストが送信先だったら if(ListBox1->Selected[i]==true) SendSystemData("ToClient"+IntToStr(i-1)+"\x01"+str ,ClientSocket1->Socket); } } } Memo1->Text = ""; } //--------------------------------------------------------------------------- // 自分がサーバーの時クライアントからの受信 void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender, TCustomWinSocket *Socket) { AnsiString dat; int del; dat = Socket->ReceiveText(); // システムコマンドかどうか if(dat.AnsiPos("\x01")==1) ServerReceiveSystemData(dat,Socket); else Memo2->Lines->Add(dat); } //--------------------------------------------------------------------------- // 自分がクライアントの時サーバーからの受信 void __fastcall TForm1::ClientSocket1Read(TObject *Sender, TCustomWinSocket *Socket) { AnsiString str; str = ClientSocket1->Socket->ReceiveText(); // システムコマンドだったら if(str.AnsiPos("\x01")==1) ClientReceiveSystemData(str); else Memo2->Lines->Add(str); } //--------------------------------------------------------------------------- // 通信を切断する void __fastcall TForm1::Button5Click(TObject *Sender) { /* mciSendString("open cdaudio", NULL, 0, NULL); mciSendString("set cdaudio door closed",NULL, 0, NULL); mciSendString("close cdaudio", NULL, 0, NULL); */ // 自分がサーバーの時は切断する事をクライアントに伝える /* if(ServerSocket1->Active==true) { Button1Click(NULL); for(int i=0;i < ListBox1->Items->Count;i++) SendSystemData("ServerDown",ServerSocket1-> Socket->Connections[i]); } */ ClientSocket1->Close(); ServerSocket1->Close(); ListBox1->Items->Text = ""; StatusBar1->Panels->Items[0]->Text = "disconnect"; StatusBar1->Panels->Items[1]->Text = ""; Button6->Visible = false; } //--------------------------------------------------------------------------- // 終了処理 void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { Button5Click(Form1); } //--------------------------------------------------------------------------- // サーバーに繋がってるクライアントの再表示 void __fastcall TForm1::Button1Click(TObject *Sender) { // 自分がサーバーだったら if(ServerSocket1->Active == true) { int n; AnsiString str; n = ServerSocket1->Socket->ActiveConnections; ListBox1->Items->Clear(); for(int i=0;iSocket->Connections[i]->RemoteHost; if(str =="") str=ServerSocket1->Socket-> Connections[i]->RemoteAddress; ListBox1->Items->Add(str); } } else // 自分がクライアントだったら { SendSystemData("ClientMemberRequest",ClientSocket1->Socket); } } //--------------------------------------------------------------------------- // 自分がクライアントの時、勝手に切断されたら void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender, TCustomWinSocket *Socket) { Button5Click(ClientSocket1); } //--------------------------------------------------------------------------- // 自分がサーバーでクライアントが切断したとき void __fastcall TForm1::ServerSocket1ClientDisconnect(TObject *Sender, TCustomWinSocket *Socket) { int del=0; // 切断したクライアントを探す while(ServerSocket1->Socket->Connections[del++] != Socket); // リストボックスから消す ListBox1->Items->Delete(del-1); ListBox1Click(ServerSocket1); //statusBar の初期化 // 接続しているクライアントに番号を振りなおす int n = ServerSocket1->Socket->ActiveConnections; for(int i=del;iSocket->Connections[i]); } // クライアントに切断したホストが誰かを知らせる for(int i=0;iSocket->Connections[i]); } } //--------------------------------------------------------------------------- // 新しくクライアントが接続してきたら void __fastcall TForm1::ServerSocket1ClientConnect(TObject *Sender, TCustomWinSocket *Socket) { int n; n = ServerSocket1->Socket->ActiveConnections; // リストボックスに新しいホストの名前を加える AnsiString str; str = ServerSocket1->Socket->Connections[n-1]->RemoteHost; if(str =="") str=ServerSocket1->Socket-> Connections[n-1]->RemoteAddress; ListBox1->Items->Add(str); // 新しいホストに番号を教える SendSystemData("Host No:"+AnsiString(n), ServerSocket1->Socket->Connections[n-1]); // 既存のホストにホストが加わった事を知らせる for(int i=0;iSocket->Connections[i]; str = soc->RemoteHost; if(str=="") str=soc->RemoteAddress; SendSystemData("AddHost:"+str,soc); } // 新しいホストに接続中のホストのリストを送る SendSystemData("ClientMemberAnswer"+(AnsiString)"Server\n" +ListBox1->Items->Text, ServerSocket1->Socket->Connections[n-1]); } //--------------------------------------------------------------------------- // システムデータを送る void TForm1::SendSystemData(AnsiString str,TCustomWinSocket *Socket) { Socket->SendText("\x01"+str); } //------------------------------------------------ // クライアントがシステムデータを受けたら void TForm1::ClientReceiveSystemData(AnsiString str) { // 送られたデータが何番目のシステムデータか検索する int cmd=0; while(str.AnsiPos( ClientSysCom[cmd])!=2 && cmdPanels->Items[0]->Text = "Host No:"+str; break; case 1: // ClientMemberAnswer ListBox1->Items->Text = str; break; case 2: // ServerDown ClientSocket1->Close(); StatusBar1->Panels->Items[0]->Text = "disconnect"; ListBox1->Items->Clear(); ListBox1Click(ClientSocket1); // status bar の初期化 break; case 3: // DeleteHost No: int del; del = StrToInt(str); ListBox1->Items->Delete(del); ListBox1Click(ClientSocket1); break; case 4: // AddHost: if(ListBox1->Items->Text=="") { ListBox1->Items->Add("Server"); ListBox1->ItemIndex = 0; } ListBox1->Items->Add(str); break; } } //------------------------------------------------ // サーバーがシステムデータを受け取ったら void TForm1::ServerReceiveSystemData(AnsiString str, TCustomWinSocket *Socket) { for(;;) { int cmd=0; AnsiString str1,str2,str3; while(str.AnsiPos(ServerSysCom[cmd])!=2 && cmdItems->Text,Socket); str2 = str; str2.Delete(1,1); break; case 1: // ToClient str1 = str.SubString(10,str.Length()-9); str2 = str1; str2.Delete(1,str1.AnsiPos("\x01")); if(str2.AnsiPos("\x01")) str3 = str2.SubString(1,str2.AnsiPos("\x01")-1); else str3 = str2; // 相手のNoの抽出 str1 = str1.SubString(1,str1.AnsiPos("\x01")-1); // 相手にメッセージ本体のみを抽出して送る ServerSocket1->Socket->Connections[StrToInt(str1)] ->SendText(str3); break; } if(!str2.AnsiPos("\x01")) break; str = str2.Delete(1,str2.AnsiPos("\x01")-1); } } //---------------------------------------- // 緊急時 // 自分がサーバーの時、指定したクライアントを強制的に切断する void __fastcall TForm1::Button6Click(TObject *Sender) { if(ServerSocket1->Active==true) { int a=MessageDlg( "本当にそのクライアントを切断しても良いですか?" ,mtInformation,TMsgDlgButtons()<Items->Text!="") ServerSocket1->Socket->Connections[ListBox1->ItemIndex] ->Close(); } } //--------------------------------------------------------------------------- // 接続先をキーボードで選んだら void __fastcall TForm1::ListBox1KeyPress(TObject *Sender, char &Key) { StatusBar1->Panels->Items[1]->Text = "Talk to:"+ListBox1->Items->Strings[ListBox1->ItemIndex]; } //--------------------------------------------------------------------------- // 接続先をマウスで選んだら void __fastcall TForm1::ListBox1Click(TObject *Sender) { // if((ClientSocket1->Active && ListBox1->ItemIndex>=0) // || (ServerSocket1->Active && ListBox1->SelCount)) if(ListBox1->SelCount) { StatusBar1->Panels->Items[1]->Text = "Talk to:"+ListBox1->Items->Strings[ListBox1->ItemIndex]; } else StatusBar1->Panels->Items[1]->Text = ""; } //--------------------------------------------------------------------------- // フォームのサイズを変更したら void __fastcall TForm1::FormResize(TObject *Sender) { Memo1->Height = Panel3->Height/2; } //--------------------------------------------------------------------------- // メインメニューの[ファイル|終了]を押したら void __fastcall TForm1::Exit1Click(TObject *Sender) { Close(); } //--------------------------------------------------------------------------- // 接続設定メニューをおしたら void __fastcall TForm1::ConnectMenuClick(TObject *Sender) { Panel2->Visible=!Panel2->Visible; SpeedButton2->Down=!SpeedButton2->Down; } //--------------------------------------------------------------------------- void __fastcall TForm1::SpeedButton2Click(TObject *Sender) { Panel2->Visible=!Panel2->Visible; } //--------------------------------------------------------------------------- // エディタ設定メニューを押したら void __fastcall TForm1::N2Click(TObject *Sender) { Panel4->Visible=!Panel4->Visible; SpeedButton1->Down=!SpeedButton1->Down; } //--------------------------------------------------------------------------- void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { Panel4->Visible=!Panel4->Visible; } //--------------------------------------------------------------------------- // ボトムバーメニューを押したら void __fastcall TForm1::N3Click(TObject *Sender) { Panel1->Top = StatusBar1->Top-30; Panel1->Visible=!Panel1->Visible; FormResize(MainMenu1); } //--------------------------------------------------------------------------- // リターンを押すごとに自動で送信する void __fastcall TForm1::Memo1KeyUp(TObject *Sender, WORD &Key, TShiftState Shift) { if(Key==VK_RETURN && CheckBox1->Checked) Button2Click(Memo1); } //--------------------------------------------------------------------------- // ヘルプ void __fastcall TForm1::Help1Click(TObject *Sender) { AnsiString str; str = (AnsiString)"サーバーになる場合は接続サービスかポートを"+ "設定して server modeボタンを押してください。clientが接続"+ "してくると左下のリストボックスに相手のHostが表示されるので、"+ "通信する相手を選んでください。右下にメッセージを書いて"+ " send msgで送信します。\n"+ "クライアントになる場合は相手の接続サービスかポートと、接続先"+ "を設定して client modeボタンを押します。serverと同じように"+ "相手を選んでメッセージを送ります。\n"+ "接続設定を押すと、メッセージが書きやすくなります。"; ShowMessage(str); } //---------------------------------------------------------------------------