SimpleServer(Windows), SimpleClient(Linux)間、
SimpleServer(Linux), SimpleClient(Windows)間
で漢字も正しく通信できるようにしましょう。
Windows版はShift-JIS、Linux版はUTF-8になっているので、今のままでは
漢字でメッセージ交換ができません。
ここでは、アプリケーション間のプロトコルとして文字列はUTF-8を使うことにします。
つまり、Windows版SimpleClient, SimpleServerに
送信時:UTF-8に変換する
受信時:Shift-JISに変換する
機能を追加します。
stdThread.cpp、stdThread.hにUTF-8<=>Shift-JISの変換関数を追加しました。
ネットワークプログラミングの本質とは少し離れているので、詳しく解説はしませんが
ソースコードのコメントと使い方を見ていただければ、ご理解いただけると思います。
それでは、プロジェクトのファイルを更新して、SimpleServer.cpp、SimpleClient.cppも
変更しましょう。
【SimpleServer.cpp】 ///////////////////////////////////////////////// // function // 受信処理 // parameter // なし // return // TRUE/FALSE ///////////////////////////////////////////////// BOOL DoRecv() { BOOL fRet = TRUE; char szRecvBuffer[RCVBUFSIZE + 1]; // 受信バッファ int iSize; fd_se rfds; struct timeval tv; fprintf(stderr, “DoRecv()\n”); while (1) { tv.tv_sec = 0; tv.tv_usec = 10 * 1000; // 10msec FD_ZERO(&rfds); FD_SET(m_fdClient, &rfds); select(FD_SETSIZE, &rfds, NULL, NULL, &tv); // タイムアウトまでSleepと同等 // キー入力で中断 if (CheckKey()) { fprintf(stderr, ” OK:Abort by key\n”); break; } if (FD_ISSET(m_fdClient, &rfds)) { memset(szRecvBuffer, 0, sizeof(szRecvBuffer)); if ((iSize = recv(m_fdClient, szRecvBuffer, RCVBUFSIZE, 0)) <= 0) { if (iSize == 0) // 0バイトの受信は切断検知 -1はエラー fprintf(stderr, “Disconnected %d\n”, WSAGetLastError()); else fprintf(stderr, “Err:recv %d\n”, WSAGetLastError()); fRet = FALSE; break; } else { #if 0 fprintf(stderr, “%s\n”, szRecvBuffer); #else // UTF-8で受信したので、SJISに変換して表示する int iSize = 0; LPBYTE pbDest = NULL; ConvUtf8toSJis((LPBYTE)szRecvBuffer, NULL, &iSize); pbDest = (LPBYTE)calloc(iSize, sizeof(BYTE)); ConvUtf8toSJis((LPBYTE)szRecvBuffer, pbDest, &iSize); fprintf(stderr, “%s\n”, pbDest); SAFE_FREE(pbDest) #endif } } } return(fRet); }
【SimpleClient.cpp】 int main(int argc, char *argv[]) { char szKeyInBuff[81]; #if 0 #else int iSize; LPBYTE pbDest = NULL; #endif m_fdClient = INVALID_SOCKET; // 起動パラメータチェック if (argc != 3) { fprintf(stderr, “Usage: %s <ServerAddress> <ServerPort>\n”, argv[0]); goto L_END; } // ソケットライブラリの初期化 if (InitSocketLib() == FALSE) goto L_END; // ソケットの作成と接続処理 // m_fdClientが接続済み状態になる if (CreateAndConnectSocket(argv[1], (WORD)atol(argv[2])) == FALSE) goto L_END; // メニューの表示 DispMenu(); while (1) { // キーボードから入力された文字列が’q’なら終了 // ‘m’ならメッセージを入力後は送信する switch (GetKeyString(szKeyInBuff, sizeof(szKeyInBuff))) { case 0: // 入力なし、何もしない break; case CMD_QUIT_CHAR: // ‘q’入力終了 goto L_END; case CMD_SEND_MSG_CHAR: // ‘m’入力szKeyInBuffに文字列が格納されている #if 0 DoSend(szKeyInBuff, strlen(szKeyInBuff)); #else // S-JISをUTF-8に変換して送信 iSize = 0; pbDest = NULL; ConvSJistoUtf8((LPBYTE)szKeyInBuff, NULL, &iSize); pbDest = (LPBYTE)calloc(iSize, sizeof(BYTE)); ConvSJistoUtf8((LPBYTE)szKeyInBuff, pbDest, &iSize); DoSend((char *)pbDest, iSize); SAFE_FREE(pbDest) #endif // メニューの表示 DispMenu(); break; } } L_END: // 切断とすべてのソケットの破棄 Stop(); // ソケットライブラリの開放 UninitSocketLib(); return(0); }