// ---------------------------------------------------------------------------- // ■小さな小さなサーバ // ---------------------------------------------------------------------------- //【機能】 // Windows Socket APIの使用方法を理解するためだけの、とにかく小さなサーバである。 // 単純化のために接続クライアント数=1,クライアントはTelnetで接続するものとする。 // 単にクライアントから送られてきたメッセージを返信するだけのアプリケーションである。 // [enter]キーが押されるまでの1行を1メッセージとする。 // ---------------------------------------------------------------------------- // 【設定方法】 // 本ソースをC++ファイルとして追加したあと、ライブラリ"WS2_32.LIB"をソースと同じ // フォルダにコピーすること。 // ---------------------------------------------------------------------------- //【Windows 7でTelnetを動作させるための設定】 // Windows 7 でTelnetを利用するには、以下の準備作業を行わなければならない。 // (1) TelnetクライアントおよびTelnetサーバーの機能の有効化 // (2) WindowsファイアウォールによるTelnetの許可 // (3) Telnet機能のサービス開始 // // 設定方法は以下のとおり。 // // (1)TelnetクライアントおよびTelnetサーバーの機能の有効化 // ・「コントロールパネル」から「プログラム」をクリック // ・「プログラムの機能」の「Windowsの機能の有効化または無効化」をクリック // ・機能一覧から「Telnetクライアント」と「Telnetサーバー」にチェックを入れ // 「OK」ボタンを押す // ・再起動を促す画面が表示されたら再起動する // // (2) WindowsファイアウォールによるTelnetの許可(上記(1)で以下が設定されるバージョンもある) // ・「コントロールパネル」から「システムとセキュリティ」をクリック // ・「Windowsファイアウォール」の「Windowsファイアウォールによるプログラムの許可」をクリック // ・少し時間がかかるがまもなくして「許可されたプログラム及び機能」一覧が表示されるので // ・画面右上の「設定の変更」ボタンをクリックする。 // ・「Telnet」を探し、「名前」項目と、ご利用のインターネット接続に関する項目の // 「ホーム/社内(プライベート)」、「パブリック」のどちらかあるいは両方にチェックを入れる。 // ・「OK」ボタンをクリックして、画面右上の×をクリックして画面を閉じる。 // // (3) Telnet機能のサービス開始 // ・画面右下の「スタート」「コンピュータ」で右クリックし、 // 表示項目から「管理」を選択する。 // ・画面左の「コンピュータの管理(ローカル)項目一覧から「サービスとアプリケーション」を選択 // ・項目の左の右向き三角をクリックして項目を展開し、「サービス」を選択 // ・サービス一覧から「Telnet」を選択し、ダブルクリック // ・Telnetのプロパティ画面が表示されるので、スタートアップの種類プルダウンメニューから // 「自動」を選択 // ・画面下の「適用」ボタンをクリックして「サービスの状態」項目の「開始」ボタンをクリック // ・「サービスの状態」が「開始」と表示されたことを確認して「OK」ボタンをクリックして、 // 画面右上の×をクリックして画面を閉じる。 // ---------------------------------------------------------------------------- // 【実行方法】 // 本例のサーバプログラムを実行させ、クライアントアクセス待ちにした状態で、 // MS DOSプロンプトを起動し、以下のように操作する (????はユーザ環境で変わる) // 以下の(入力)と書いてある行が入力するところである。他は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] ("> "以降を入力) //(サーバ側にクライアントからアクセスがあった旨の表示がなされる) // クライアント側(Telnet)から入力して[enter]をキーインすると、 // サーバーが受け取った文字列を返却されTelnet側に表示される。 // [ctrl]を押したままZをキーインし、[enter]を入力すると終了 // ---------------------------------------------------------------------------- #include "stdio.h" #include "string.h" #include "winsock2.h" #pragma comment(lib, "WS2_32.LIB") void dspErr(char msg[]){ printf("\n** %s ** エラー番号 %d\n", msg, WSAGetLastError()); } int main(int argc, char argv[]) { WSADATA wsaData; SOCKET s,clientSoc; SOCKADDR_IN name = { AF_INET }, client; int client_addr =sizeof(SOCKADDR); WSAStartup(2, &wsaData); // Windows Socket API開始 name.sin_port=htons(2048); // 待受けポート番号=2048 s=socket(AF_INET,SOCK_STREAM,0); // TCPのバイトストリーム bind(s,(SOCKADDR *)&name,sizeof(SOCKADDR)); // サーバーソケット listen(s,1); // 受信待機(接続数1) clientSoc=accept(s,(SOCKADDR *)&client, &client_addr); // 接続要求待ち printf("アクセスがありました\nポート %d : アドレス = %s\n", client.sin_port,inet_ntoa(client.sin_addr)); // 自画面に表示 char message[100]; sprintf(message,"\x1B[2Jこんにちは\r\n");// [ESC][2Jは画面クリア// メッセージ送信 if(send(clientSoc, message,strlen(message),0)==SOCKET_ERROR) dspErr("送信失敗"); int notEnd=true; while(notEnd){ // 継続フラグがtrueの間繰り返し int ed; char recBuf[100],recDT[1024];recDT[0]=0; while(1){ // 永久ループ('\n'が来たら break) int ed; int nRecv=recv(clientSoc,recBuf,sizeof(recBuf),0); // 受信待ち if(nRecv==SOCKET_ERROR) dspErr("受信失敗"); else { recBuf[nRecv]=0; strcat(recDT,recBuf); // 受信データを連結 if(recBuf[nRecv-1]==0x1A) notEnd=false; // 最後が[ctrl]Zのとき終わり ed=strlen(recDT);if(recDT[ed-1]=='\n') break; // '\n'最後が'\n'でbreak } } ed=strlen(recDT);recDT[ed-2]=0;//最後は"\r\n"に決まっているので文字の終了 0 を埋め込む sprintf(message,"\r\nサーバ受信データ[%s]\r\n",recDT); // 受信データをクライアントに送信 if(send(clientSoc, message,strlen(message),0)==SOCKET_ERROR) dspErr("送信失敗"); } shutdown(s,SD_BOTH); closesocket(s); // セッション終了 WSACleanup(); // WSA終了 return 0; }