結果だけでなく過程も見てください

この日記のはてなブックマーク数

2017-12-28

Kotlin文法まとめ

最近iPhoneアプリの移植で触り始めました。
メモとして適宜追加していきます。

when文 (Java/Cでいうswitch文)

変数fruitで分岐させる場合。Java/Cでいうbreakは不要です。

val FRUIT_APPLE    :Int = 0
val FRUIT_BANANA   :Int = 1
val FRUIT_MELON    :Int = 2
val FRUIT_LEMON    :Int = 3

 :

when ( fruit )
{
    FRUIT_APPLE              -> print("RINGO")
    FRUIT_BANANA             -> print("BANANA")
    FRUIT_MELON, FRUIT_LEMON -> print("MELON or LEMON")
    else                     -> print("OTHER")
}

ブロックも使えます。また複数の文を書きたい場合は、セミコロンで区切ります。

when ( fruit )
{
    FRUIT_APPLE              -> { print("RINGO"); fruit_name="RINGO" }
    FRUIT_BANANA             -> { print("BANANA"); fruit_name = "BANANA" }
    FRUIT_MELON, FRUIT_LEMON -> { print("MELON or LEMON"); fruit_name="MELON or LEMON" }
    else                     -> { print("OTHER"); fruit_name="OTHER" }
}

私はあまり好みではないですが、引数なしのwhen文という書き方もあるようです。

when
{
    fruit == FRUIT_APPLE                         -> { print("RINGO"); fruit_name="RINGO" }
    fruit == FRUIT_BANANA                        -> { print("BANANA"); fruit_name = "BANANA" }
    fruit == FRUIT_MELON || fruit == FRUIT_LEMON -> { print("MELON or LEMON"); fruit_name="MELON or LEMON" }
    else                                         -> { print("OTHER"); fruit_name="OTHER" }
}

2017-10-31

Raspberry Pi 3で64GB以上のmicroSDカードを使う方法

Raspberry Pi始めました!
…んが、開始初日から躓いてしまいました。

64GBのmicro SDカードを購入したのですが、Raspberry Pi 3ではFAT32でフォーマットしたカードしか
認識できないようで、32GB以上のカードの場合は有名なSD card Formatter 5.0(現時点の最新版)を使っても、
自動でexFATフォーマットになってしまいRaspberry Piで正しく認識してくれないのでした。

どーするか。

解決

SD card Formatter 4.0を使ってください。公式からは見つからず、ダウンロードはこのあたりから…。
https://sd-card-formatter.jp.uptodown.com/windows

で、起動したら[フォーマットオプション]から、[論理サイズ調整]をONにしてからフォーマットを
開始してください。これだけでRaspberry PimicroSDカードを正しく認識し、OSインストールを進めることができます。

余談

この解決法に辿りつくまでBuffalo製のDisk Formatter Ver.2.08やHP USB Disk Storage Format Tool 2.2.3を
試したのですが、前者はmicroSDカードのライトプロテクトを外してくださいといった意味不明なこと
microSDカードにはWriteProtectはない)を言ってきたり、後者はFAT32でフォーマット出来たにも関わらず
Raspberry PiOSインストール中にエラーが起こったりと、なかなかうまくいきませんでした。

ここは素直にSD Card Formatter 4.0を使用するのが良いようです。

2017-07-28

ドラゴンクエストXI用 ドラクエ2最強ステータスのふっかつのじゅもん

明日(もう今日か)発売のドラクエ11では過去(ドラクエ2?)のふっかつのじゅもんが使えるようです!たぶん。

家の押入れを漁ったところ、小学生時代自分が書いたであろうドラクエ2の最強ステータスの
ふっかつのじゅもんがありましたので記念に投稿しておきます(使えなかったらごめんね)

最早ドラクエ少年の通過儀礼となっているふっかつのじゅもん写し間違えがよほど怖かったのか、
同じステータスのじゅもんを3つ残してます…やるな!小学生の頃のオレw

いちおう3つとも載せときます。ステータスは一緒です。

その1

やぼた ちけれ ろれきか
えせみ かさえ ぷねなず
わぽつ はげぼ ぴぴすて
ぼびす めてれ わたじぴ
かばる すもめ はむおぽ い

その2

いねわ わもう うあぴぜ
ざざう りわゆ ほばじち
くひわ じぷの ほぺまら
れぷふ かげり てずかぬ
ぱぽび ごうせ がるわほ ぼふ

その3

えひげ ごるこ さこらは
ねらぶ まやほ ねざぐせ
かはわ ずぽふ めえゆぎ
ざきよ ちぱぜ むうにり
せてし かのゆ おいかぶ ぬぶ

なつかしいですねぇ。
もょもとでおなじみの以下も使えるそうです。
いや〜楽しみだ。

ゆうて いみや おうきむ
こうほ りいゆ うじとり
やまあ きらぺ ぺぺぺぺ
ぺぺぺ ぺぺぺ ぺぺぺぺ
ぺぺぺ ぺぺぺ ぺぺぺぺ ぺぺ

小学校自体のメモはこれ。意外に綺麗ですね。
f:id:taiyakisun:20170729003403j:image

2017-07-19

スキルポイント自動振り分け for DQX オンラインマニュアル (ver 1.2.1)

アプリの概要

スキルポイント自動振り分け for DQXは、
「どのスキルに、何ポイント振り分けたいか」を入力するだけで
各職業のスキルに何ポイント振ればよいかを自動計算してくれるiOSアプリ
です(もちろん無料)。

ダウンロードはこちらから。
https://itunes.apple.com/jp/app/%E3%82%B9%E3%82%AD%E3%83%AB%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E8%87%AA%E5%8B%95%E6%8C%AF%E3%82%8A%E5%88%86%E3%81%91-for-dqx/id1261399639?mt=8

このツールは大きく分けて3つの画面から構成されています。
以下、各画面について説明します。


職業画面

各職業がどれくらいスキルポイントを所持しているかを入力する画面です。
レベルと特訓ポイントで決まります。

f:id:taiyakisun:20171110004537p:image

スクリーンショットの(1)をタップすることで、この画面が表示されます。

職業の持つスキルポイントの入力

(2)のテキストボックスをタップしてスキルポイントを手動で入力できます。
手動入力が面倒な方は、(4)をタップして自動で読み込むこともできます。

(4)の[公式Webから自動読み込み]をタップすると、アプリ内のブラウザが起動し、公式サイトが表示されます。
ログイン後、つよさ→スキルポイントのページを表示し[読み込む]ボタンを押すことで全職業まとめて自動で読み込むことが可能です。

職業の優先順位を設定する

職業の優先順位を(3)で調整します。
アイコンを長押しして上下にドラッグすることにより優先順位を変えることができます。
一番上にある職業が、最優先にスキルが割り振られるようになっています。
スクリーンショットの例では、武闘家が一番優先され、盗賊が二番目に優先・・・となります。

その他の機能

(5)は入力した数値のセーブとロード行う機能です。
職業の持つスキルポイント、後述するどのスキルに何ポイント降るのか、所持しているマスタースキルポイントのセーブ/ロードが可能です。

(6)はスキル計算を開始し、結果画面に移動します。


スキル画面

どのスキルに、何ポイント振りたいのかを入力する画面です。
所持しているマスタースキルポイントもこの画面で入力します。

f:id:taiyakisun:20171110004610p:image

スクリーンショットの(1)をタップすることで、この画面が表示されます。

振り分けたいスキルポイントの入力

(2)のテキストボックスをタップすると、ポイント入力用の画面が表示されます。
この画面については「スキル選択画面」の項目をご参照ください。


(4)をタップすることで、所持しているマスタースキルポイントを入力することができます。

優先的に振り分けたいスキルの順番

また職業と同じように、(3)で優先的に振り分けたいスキルの順番を調整できます。
アイコンを長押しして上下にドラッグすることにより優先順位を変えることができます。
一番上にあるスキルが、最も優先するスキルとなります。

パッシブスキル設定機能

「P」と書かれた(7)のボタンを押すと、パッシブスキル設定画面が表示されます。
この画面については「パッシブスキル設定画面」の項目をご参照ください。

その他の機能

(5)(6)は職業画面の(5)(6)とまったく同じ機能です。

スキル選択画面

取りたいスキルのポイントを入力する画面です。
ポイントの数値を直接入力するか、取りたいスキルを選択することで
スキルに対応するポイントを自動で入力することができます。

f:id:taiyakisun:20171110004644p:image

(1)から直接数値を入力して、スキルポイントを入力できます。
(2)のスキル一覧から取りたいスキルをタップすることで、対応するスキルポイントが自動で入力できます。
(戻る)が書かれているオレンジ色の部分をタップすると、入力キャンセルして元の画面に戻ります。

パッシブスキル設定画面

選んだパッシブスキルを一括して設定する画面です。
主にフルパッシブを設定する際に使用します。

f:id:taiyakisun:20171110004714p:image

(1)取りたいパッシブスキルにチェックを入れます。デフォルトでフルパッシブが取れるよう、すべての項目にチェックが入っています。
(2)ボタンを押すことで選択したパッシブスキルのポイントが入力されます。
(3)設定せずに前の画面に戻ります。

結果画面

どの職業のどのスキルに何ポイント振ればいいか(結果)を表示する画面です。

また割り当てられなかったスキルもここで表示します。
割り当て不可は、マスタースキルポイントを使わなかった場合と、使った場合それぞれを表示します。

f:id:taiyakisun:20171110004739p:image

スクリーンショット魔法使いの例(スワイプすれば全職業がありますが)では、以下の結果になります。

  • 魔法使いのもっているスキルポイント213はすべて使い切っている(残り0で、0/213表記)
  • 魔法使いのときのマスタースキルポイント26はすべて使い切っている(残り0で、0/26表記)
  • 短剣には、この職業ではポイントを振らない(0ポイント)。全職業の割り振り状況としては、180ポイント取りたいところ、180振ることができている。
  • ムチには、この職業ではポイントを振らない(0ポイント)。全職業の割り振り状況としては、スキルを取らないので0/0表記になっている。
  • 両手杖には、この職業ではスキルポイント125ポイント、マスタースキルポイント26を割り当てる

 全職業の割り振り状況としては、180ポイント取りたいところ、150振ることができている(マスタースキルポイント込では150 + 26の数値)

  • 盾には、この職業ではポイントを振らない(0ポイント)。全職業の割り振り状況としては、180ポイント取りたいところ、180振ることができている。
  • まほうには、この職業では88ポイント振る。全職業の割り振り状況としては、88ポイント取りたいところ、88振ることができている。

  • マスタースキルポイントを使わない場合は、両手杖が30ポイント不足していて、割り当てられなかった
  • マスタースキルポイントを使っても、ツメが4ポイント不足していて、割り当てられなかった



注意:マスタースキルポイントの使用有無で表記を分けている理由

マスタースキルポイント込みでスキルの割り振りを考えると、
転職するたびにマスタースキルポイントの調整が必要になる可能性があり、面倒です。
この面倒がイヤな方(自分もそうです)向けに、マスタースキルポイントを使用せずに
割り当てられるかも別途表記しています。



今後の予定

すべて実装するかはわかりませんが、できる限り対応します。

  • アルゴリズムの改善(適宜)
  • 高速化(適宜)
  • バグ修正(適宜)
  • 新職業/新スキル追加(適宜)
  • 結果画面のわかりやすさ改善(適宜)
  • セーブロードのスロットを見やすくするかも?(セーブ時刻を表示するとか)

2017-06-27

ちょっとしたTCP/IP通信でいろいろテストしたいときのコードテンプレ(Windows/Linux両方ビルド可能!)

タイトル通りです。

  • テスト用です
  • コピって適当に改造して使いましょう
  • エラー処理は無いに等しいです
  • アドレスはIPv4しか使えません
  • 一部機能が未実装です
  • 2時間くらいでとりあえず上げたものです。徐々に修正していきます(これいつものやつや!)。

ビルド

Windows

Visual Studio Community 2015で動作確認済みです。
追加のライブラリとして「ws2_32.lib」を追加しといてください。
(プロジェクトのプロパティ→リンカー→入力→追加の依存ファイル)
あとは普通にビルドできます。

Linux

gcc 4.8.5で動作確認済みです。

gcc ./main.cpp -o main -lstdc++ -lpthread

使用方法

サーバー
実行ファイル server <リッスンするIPアドレス> <リッスンするポート>

■例
./main server 192.168.1.10 19876

クライアント
実行ファイル client <接続先IPアドレス> <接続先ポート> <接続元IPアドレス> <接続元ポート> <サーバーに送るメッセージ>

※接続元

■例
./main client 192.168.1.10 19876 0.0.0.0 0 ahaha

ソースコード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#ifdef WIN32
    #include <WinSock2.h>
    #include <Windows.h>
    #include <process.h>
#else
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <pthread.h>
#endif


#ifdef WIN32
    #define HERROR                          WSAGetLastError()
    #define SAFE_SOCK_CLOSE(sock)           if((sock) != INVALID_SOCKET){ closesocket((sock)); (sock)=INVALID_SOCKET; }
    #define SOCK_TYPE                       SOCKET
    #define SOCKLEN_TYPE                    int
    #define SLEEP_SEC(sec)                  Sleep((sec) * 1000)
    #define SET_SOCKADDR_IPV4(addr, value)  (addr).sin_addr.S_un.S_addr = (value)
#else
    #define HERROR                          h_errno
    #define INVALID_SOCKET                  (-1)
    #define SAFE_SOCK_CLOSE(sock)           if((sock) != INVALID_SOCKET){ close((sock)); (sock)=INVALID_SOCKET; }
    #define SOCK_TYPE                       int
    #define SOCKLEN_TYPE                    socklen_t
    #define SLEEP_SEC(sec)                  sleep((sec))
    #define SET_SOCKADDR_IPV4(addr, value)  (addr).sin_addr.s_addr = (value)
#endif

#define SAFE_DELETE(p)  if(p){ delete(p); (p)=NULL; }


const char* errno_str()
{
    switch ( errno )
    {
        case 1:   return "EPERM";
        case 2:   return "ENOENT";
        case 3:   return "ESRCH";
        case 4:   return "EINTR";
        case 5:   return "EIO";
        case 6:   return "ENXIO";
        case 7:   return "E2BIG";
        case 8:   return "ENOEXEC";
        case 9:   return "EBADF";
        case 10:  return "ECHILD";
        case 11:  return "EAGAIN or EWOULDBLOCK";
        case 12:  return "ENOMEM";
        case 13:  return "EACCES";
        case 14:  return "EFAULT";
        case 15:  return "ENOTBLK";
        case 16:  return "EBUSY";
        case 17:  return "EEXIST";
        case 18:  return "EXDEV";
        case 19:  return "ENODEV";
        case 20:  return "ENOTDIR";
        case 21:  return "EISDIR";
        case 22:  return "EINVAL";
        case 23:  return "ENFILE";
        case 24:  return "EMFILE";
        case 25:  return "ENOTTY";
        case 26:  return "ETXTBSY";
        case 27:  return "EFBIG";
        case 28:  return "ENOSPC";
        case 29:  return "ESPIPE";
        case 30:  return "EROFS";
        case 31:  return "EMLINK";
        case 32:  return "EPIPE";
        case 33:  return "EDOM";
        case 34:  return "ERANGE";
        case 35:  return "EDEADLK or EDEADLOCK";
        case 36:  return "ENAMETOOLONG";
        case 37:  return "ENOLCK";
        case 38:  return "ENOSYS";
        case 39:  return "ENOTEMPTY";
        case 40:  return "ELOOP";
        case 42:  return "ENOMSG";
        case 43:  return "EIDRM";
        case 44:  return "ECHRNG";
        case 45:  return "EL2NSYNC";
        case 46:  return "EL3HLT";
        case 47:  return "EL3RST";
        case 49:  return "EUNATCH";
        case 51:  return "EL2HLT";
        case 52:  return "EBADE";
        case 53:  return "EBADR";
        case 54:  return "EXFULL";
        case 56:  return "EBADRQC";
        case 57:  return "EBADSLT";
        case 60:  return "ENOSTR";
        case 61:  return "ENODATA";
        case 62:  return "ETIME";
        case 63:  return "ENOSR";
        case 64:  return "ENONET";
        case 65:  return "ENOPKG";
        case 66:  return "EREMOTE";
        case 67:  return "ENOLINK";
        case 70:  return "ECOMM";
        case 71:  return "EPROTO";
        case 72:  return "EMULTIHOP";
        case 74:  return "EBADMSG";
        case 75:  return "EOVERFLOW";
        case 76:  return "ENOTUNIQ";
        case 77:  return "EBADFD";
        case 78:  return "EREMCHG";
        case 79:  return "ELIBACC";
        case 80:  return "ELIBBAD";
        case 81:  return "ELIBSCN";
        case 82:  return "ELIBMAX";
        case 83:  return "ELIBEXEC";
        case 84:  return "EILSEQ";
        case 85:  return "ERESTART";
        case 86:  return "ESTRPIPE";
        case 87:  return "EUSERS";
        case 88:  return "ENOTSOCK";
        case 89:  return "EDESTADDRREQ";
        case 90:  return "EMSGSIZE";
        case 91:  return "EPROTOTYPE";
        case 92:  return "ENOPROTOOPT";
        case 93:  return "EPROTONOSUPPORT";
        case 94:  return "ESOCKTNOSUPPORT";
        case 95:  return "ENOTSUP or EOPNOTSUPP";
        case 96:  return "EPFNOSUPPORT";
        case 97:  return "EAFNOSUPPORT";
        case 98:  return "EADDRINUSE";
        case 99:  return "EADDRNOTAVAIL";
        case 100: return "ENETDOWN";
        case 101: return "ENETUNREACH";
        case 102: return "ENETRESET";
        case 103: return "ECONNABORTED";
        case 104: return "ECONNRESET";
        case 105: return "ENOBUFS";
        case 106: return "EISCONN";
        case 107: return "ENOTCONN";
        case 108: return "ESHUTDOWN";
        case 110: return "ETIMEDOUT";
        case 111: return "ECONNREFUSED";
        case 112: return "EHOSTDOWN";
        case 113: return "EHOSTUNREACH";
        case 114: return "EALREADY";
        case 115: return "EINPROGRESS";
        case 116: return "ESTALE";
        case 117: return "EUCLEAN";
        case 120: return "EISNAM";
        case 121: return "EREMOTEIO";
        case 122: return "EDQUOT";
        case 123: return "ENOMEDIUM";
        case 124: return "EMEDIUMTYPE";
        case 125: return "ECANCELED";
        case 126: return "ENOKEY";
        case 127: return "EKEYEXPIRED";
        case 128: return "EKEYREVOKED";
        case 129: return "EKEYREJECTED";
        default:  return "UNKNOWN";
    }
}


const char* getLocalTimeStr( time_t  curTime, 
                             char*   pszResultTime )
{
    struct tm* pt = localtime( &curTime );

    sprintf( pszResultTime, "%02d/%02d/%02d %02d:%02d:%02d", pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec );

    return pszResultTime;
}


class NetworkInfo
{
public:

    ~NetworkInfo()
    {

#ifdef WIN32
        if ( bWSASetup )
        {
            WSACleanup();
            bWSASetup = false;
        }
#endif

        SAFE_SOCK_CLOSE( sock0 );
    }

#ifdef WIN32
    WSADATA             wsaData;
    bool                bWSASetup;
#endif

    /* listening socket */
    SOCK_TYPE           sock0;

    /* サーバーならリッスンするアドレス情報     */
    /* クライアントなら送信先アドレス情報とする */
    struct sockaddr_in  addr;

    /* オプション。クライアントのときだけ使われる。クライアント側アドレスとポート。 */
    struct sockaddr_in  client_addr_forsend;


    NetworkInfo() :
#ifdef WIN32
        wsaData(),
        bWSASetup( false ),
#endif
        sock0( INVALID_SOCKET ),
        addr(),
        client_addr_forsend()
    {
    }

};


/* サーバーかクライアントの種別列挙子 */
enum NodeType
{
    eUnknown = 0,
    eServer,
    eClient
};


/* 受信関数で必要な情報 */
struct RecvInfo_t
{
    /* 受信処理で使用するソケット */
    SOCK_TYPE  recvSock_;

    RecvInfo_t( SOCK_TYPE recvSock ):
        recvSock_( recvSock )
    {
    }
};


/* 受信関数 */
#ifdef WIN32
  unsigned __stdcall recvThread( void *p )
#else
  void* recvThread( void *p )
#endif
{
    RecvInfo_t* pRecvInfo = (RecvInfo_t *)p;

    char  inbuf[2048];   /* 受信バッファ     */
    char  atimeWk[64];   /* 時刻表示ワーク用 */

    memset( inbuf, 0, sizeof( inbuf ) );
    memset( atimeWk, 0, sizeof( atimeWk ) );

    /* 情報を取得してメモリ解放しておく */
    SOCK_TYPE sock = pRecvInfo->recvSock_;
    SAFE_DELETE( pRecvInfo );

    /* 受信処理。同期とする。出力結果が混ざって表示されるが気にしない */
    recv( sock, inbuf, sizeof( inbuf ), 0 );
    printf( "%s Received Message:%s\n", getLocalTimeStr(time(NULL), atimeWk), inbuf );

    SAFE_SOCK_CLOSE( sock );

#ifdef WIN32
    return 0;
#else
    pthread_exit( NULL );
#endif
}


/*
* me <NodeType> <listening addr> <listening port>
*      or
* me <NodeType> <dest addr> <dest port> <src addr> <src port> <msg>
*
* <NodeType> "server" or "client"
*
* Only IPv4.
*/
int main( int argc, char* argv[] )
{
    if ( argc <= 1 )
    {
        fprintf( stderr, "Bad args num.\n" );
        return 1;
    }

    NodeType eNodeType = eUnknown;

    if ( strcmp( argv[1], "server" ) == 0 )
    {
        eNodeType = eServer;

        if ( argc != 4 )
        {
            fprintf( stderr, "Bad args num(Server)(%d).\n", argc );
            return 1;
        }
    }
    else if ( strcmp( argv[1], "client" ) == 0 )
    {
        eNodeType = eClient;

        if ( argc != 7 )
        {
            fprintf( stderr, "Bad args num(Client)(%d).\n", argc );
            return 1;
        }
    }
    else
    {
        fprintf( stderr, "Bad NodeType.\n" );
        return 2;
    }

    int          nFuncRet = 0;   /* Function return code */
    NetworkInfo  netInfo;
    char         atimeWk[64];

    memset( atimeWk, 0, sizeof(atimeWk) );

    
#ifdef WIN32
    nFuncRet = WSAStartup( MAKEWORD( 2, 0 ), &(netInfo.wsaData) );
    netInfo.bWSASetup = true;
    if ( nFuncRet != 0 )
    {
        fprintf( stderr, "%s WSAStartup error(%d)(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), nFuncRet, HERROR, errno, errno_str() );
        return 3;
    }
#endif


    if ( eNodeType == eServer )
    {
        /* argv */
        /* [1]:ノード種別       */
        /* [2]:リッスンアドレス */
        /* [3]:リッスンポート   */

        const char* pszAddr    = argv[2];
        const char* pszPortNum = argv[3];


        /* リッスンソケットの作成 */
        netInfo.sock0 = socket( AF_INET, SOCK_STREAM, 0 );
        if ( netInfo.sock0 == INVALID_SOCKET )
        {
            fprintf( stderr, "%s listen socket error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr(time(NULL), atimeWk), HERROR, errno, errno_str() );
            return 4;
        }

        /* バインドリッスンするアドレスとポート設定 */
        netInfo.addr.sin_family = AF_INET;
        netInfo.addr.sin_port   = htons( atoi( pszPortNum ) );    /* リッスンポート TODO:引数を信じろ! */
        SET_SOCKADDR_IPV4( netInfo.addr, inet_addr( pszAddr ) );  /* バインドアドレス TODO:引数を信じろ! */


        /* サーバーの場合はポート再利用可能 */
        {
            int nYes = 1;
            setsockopt( netInfo.sock0, SOL_SOCKET, SO_REUSEADDR, (const char *)&nYes, sizeof( nYes ) );
        }


        nFuncRet = bind( netInfo.sock0, (struct sockaddr *)&(netInfo.addr), sizeof( netInfo.addr ) );
        if ( nFuncRet == -1 )
        {
            fprintf( stderr, "%s bind(recv) error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );
            return 8;
        }


        nFuncRet = listen( netInfo.sock0, 5 );  /* backlogは5 */
        if ( nFuncRet == -1 )
        {
            fprintf( stderr, "%s listen error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );
            return 9;
        }


        /* recv loop */
        while (1)
        {
            int                 sock        = INVALID_SOCKET;
            struct sockaddr_in  client      = {0};
            SOCKLEN_TYPE        nClientLen  = sizeof( client );

            sock = accept( netInfo.sock0, (struct sockaddr *)&client, &nClientLen );
            if ( sock == INVALID_SOCKET )
            {
                fprintf( stderr, "%s accept error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );
                continue;
            }

            /* 処理用スレッドを起動 */
            RecvInfo_t* pRecvInfo = NULL;
            try
            {
                pRecvInfo = new RecvInfo_t( sock );
            }
            catch (...)
            {
                /* bad memory alloc */
                SAFE_SOCK_CLOSE( sock );
                continue;
            }

#ifdef WIN32
            unsigned int thID = 0;

            HANDLE hThread = (HANDLE)_beginthreadex( NULL,
                                                     0,
                                                     recvThread,
                                                     pRecvInfo,
                                                     0  /*CREATE_SUSPENDED*/,
                                                     &thID );
            if ( hThread == 0 )
            {
                fprintf( stderr, "%s _beginthreadex error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );

                SAFE_SOCK_CLOSE( sock );
                continue;
            }

            /* Windowsではデフォルトでpthread_detach相当の設定になっている(たぶん) */
#else
            pthread_t th = 0;

            nFuncRet = pthread_create( &th, NULL, recvThread, (void *)pRecvInfo );
            if (nFuncRet != 0)
            {
                fprintf( stderr, "%s pthread_create error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );

                SAFE_SOCK_CLOSE( sock );
                continue;
            }

            (void)pthread_detach( th );
#endif
        }

    }
    else
    {
        /* argv */
        /* [1]:ノード種別       */
        /* [2]:接続先アドレス   */
        /* [3]:接続先ポート     */
        /* [4]:接続元アドレス   */
        /* [5]:接続元ポート     */
        /* [6]:メッセージ       */

        const char* pszDestAddr    = argv[2];
        const char* pszDestPortNum = argv[3];
        const char* pszSrcAddr     = argv[4];
        const char* pszSrcPortNum  = argv[5];
        const char* pszMessage     = argv[6];


        int   sock = 0;
        char  sendmsg[256];

        memset( sendmsg, 0, sizeof( sendmsg ) );

        /* 接続先アドレス情報 */
        netInfo.addr.sin_family = AF_INET;
        netInfo.addr.sin_port = htons( atoi(pszDestPortNum) );       /* TODO:引数を信じて! */
        SET_SOCKADDR_IPV4( netInfo.addr, inet_addr(pszDestAddr) );   /* TODO:引数を信じて! */


        /* 接続元アドレス情報 */
        netInfo.client_addr_forsend.sin_family = AF_INET;
        netInfo.client_addr_forsend.sin_port = htons( atoi( pszSrcPortNum ) );    /* TODO:引数を信じて! */
        SET_SOCKADDR_IPV4( netInfo.client_addr_forsend, inet_addr(pszSrcAddr) );  /* TODO:引数を信じて! */


        sock = socket( AF_INET, SOCK_STREAM, 0 );
        if (sock == INVALID_SOCKET)
        {
            fprintf( stderr, "%s socket(send) h_errno:%d errno:%d(%s)\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );

            return 10;
        }


        /* TODO:将来的にクライアントの場合のポート再利用可能は設定するかしないか設定できるようにしたい */
        {
            int nYes = 1;
            setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&nYes, sizeof( nYes ) );
        }


        /* TODO:将来的に接続元アドレスを必ずbindするかどうかはオプション化したい */
        nFuncRet = bind( sock, (struct sockaddr *)&(netInfo.client_addr_forsend), sizeof(netInfo.client_addr_forsend) );
        if (nFuncRet == -1)
        {
            fprintf( stderr, "%s bind(send) error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );

            return 11;
        }


        nFuncRet = connect( sock, (struct sockaddr *)&(netInfo.addr), sizeof( netInfo.addr ) );
        if ( nFuncRet == -1 )
        {
            fprintf( stderr, "%s connect error(h_errno:%d)(errno:%d(%s))\n", getLocalTimeStr( time( NULL ), atimeWk ), HERROR, errno, errno_str() );
            
            return 12;
        }


        memset( sendmsg, 0, sizeof(sendmsg) );
        strncpy( sendmsg, pszMessage, sizeof(sendmsg)-1 );

        (void)send( sock, sendmsg, (int)strlen( sendmsg ), 0 );

        SAFE_SOCK_CLOSE( sock );
    }


    return 0;
}

(旧)受信側 非マルチスレッド

main.cpp 直

参考サイト

Geekなぺーじ
http://www.geekpage.jp/programming/

JM Project
https://linuxjm.osdn.jp/

がんばるかも
http://aya213.blogspot.jp/2009/04/unix_27.html