//--------------------------------------------------------------- // ■小さなチャットサーバ //--------------------------------------------------------------- // メンバー数は5名まで(変えるときはNCLIENTを変更する) // 【実行方法】 // 本例のサーバプログラムを実行させ、クライアントアクセス待ちにした状態で、 // MSDOSプロンプトを起動し、以下のように操作する (????はユーザ環境で変わる)。 // 以下は、単一のパソコンで確認するときの操作方法。遠隔操作するときは、 // localhostを別の名前かIPアドレスにする。 // 以下の("> "以降を入力)と書いてある行が入力する部分である。 // 他はTelnetが表示した文字列。 // // C:\????> telnet[enter] ("> "以降を入力) // Microsoft Telnet クライアントへようこそ // // エスケープ文字は 'CTRL+]' です // // Microsoft Telnet> unset localecho[enter] ("> "以降を入力) // ローカル エコー: オフ // Microsoft Telnet> set codeset shift jis[enter] ("> "以降を入力) // エミュレーションの種類: VT100/漢字コードセット: Shift JIS // Microsoft Telnet> open localhost 2048[enter] ("> "以降を入力) // // なお、次回以降は、 // // C:\????> telnet localhost 2048[enter] ("> "以降を入力) // // だけでよい。"Your Name?"と聞いてくるので名前を入力して[enter] // をキーインするとメンバー追加されて通信モードに入る。 // // 半角の "$by[enter]"でメンバーから抜けることができる。 // 半角の "$join[enter]"でメンバー一覧を表示する。 // // サーバで半角の "$by[enter]"を入力するとサービスを停止する。 // // 複数のMSDOSプロンプト画面を開いて上記を行うと、 // それぞれのMSDOSプロンプト画面がそれぞれのクライアントになる。 // #include "stdio.h" #include "string.h" #include "winsock2.h" #include "process.h" #pragma comment(lib, "WS2_32.LIB") #define NCLIENT 5 typedef struct { int No; // スレッド番号 int sendFlag; // 送信フラグ(排他制御用) int mode; // モード(0:未起動, 1:名前問合せ中, 2:通信中) SOCKET socket; // ソケット識別子 SOCKADDR_IN addr; // ソケットアドレス char name[22]; // 使用者名(自由でよい) }clientData; int notEnd=true; // サービス中フラグ SOCKET serverSoc; // サーバのソケット識別子 clientData client[NCLIENT];// クライアントのデータ HANDLE hThread[NCLIENT]; // クライアント用スレッドハンドル void dspErr(char msg[]){// ■エラー表示 printf("\n** %s ** Error No %d\n", msg, WSAGetLastError()); } void exitProc(){// ■サービス終了処理(サーバ上で"$by"入力で終了) char msg[]="\r\n*** Service End ***\r\n"; notEnd=false; for(int i=0; i=2) recDT[ed-2]=0; // 最後の[CR][LF]を無視 recDT[20]=0;//名前は20文字未満とする sprintf(cmess,"\r\nGreet : %s, Welcome to Mini Chat!\r\n",recDT); lockAndSend(ID,cmess); printf("\n %s joined in members.",recDT); strcpy(client[ID].name,recDT); // 名前をテーブルに保存 for(int i=0;i> %s ", client[ID].name, recDT); if(strcmp(recDT,"$by")==0){// 参加脱退 sprintf(cmess, "\r\nGreet : Good by! %s.\r\n",client[ID].name); lockAndSend(ID,cmess);// Good by送信 client[ID].mode=0; for(int i=0;i=0){ // クライアント設定 client[ID].socket=cs; client[ID].addr=addr; printf("\nAccessed Port = %d : Address = %s",// サーバ画面に表示 client[ID].addr.sin_port,inet_ntoa(client[ID].addr.sin_addr)); client[ID].mode=1; // クライアント待ちスレッド開始 hThread[ID]=(HANDLE)_beginthread(getMess,0,(void *)(client[ID].No)); } else{ // 空きクライアントなしのとき printf("\nBusy Cancel Port = %d : Address = %s\n", // ビジーとする addr.sin_port,inet_ntoa(addr.sin_addr)); // サーバ画面に表示 char cmess[]="\r\nNow Busy. Try after a while."; if(send(cs,cmess,strlen(cmess),0)==SOCKET_ERROR)dspErr("Send Error"); shutdown(cs,SD_BOTH);closesocket(cs); // ソケット解放 } Sleep(100); } exitProc(); return 0; }