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

日々の奮闘を綴る日記です。

Windowsで関数がどのlibファイルに含まれているかを確認する方法

Windowsで他人のライブラリをビルドして使用する場合など、
サンプルソースを動かしてみたら関数が未解決でリンクエラー…どのlibファイルをリンクすりゃいいんだ?
………なんて経験があると思います。今回はこの解消法をご紹介します。

ここではVisual Studioを使っていることを前提とします。

Visual Studioでは、使用するlibをプロジェクトのプロパティ→[リンカー]→[入力]→[追加の依存ファイル]に指定する必要がありますが、サンプルソースの関数がどのlibファイルに含まれているのかわからん!!といった場合は以下の方法を使います。

 

Visual Studioの開発者用コマンドプロンプトを開く

スタートメニューから開いてください。
例)Visual Studio 2017 (Community)の場合では「開発者コマンド プロンプト for VS 2017」という名前でした。

libファイルの内容をダンプする

libファイル群があるフォルダまで移動して、以下のコマンドを実行してダンプします。

link /dump /exports *.lib>liblist.txt

liblist.txtの内容を確認

あとは普通にテキストエディタでliblist.txtをオープンし、使いたい関数名で検索するだけ。liblist.txtの内容はこんな内容になっているはずです。

Dump of file maincore300.lib
File Type: LIBRARY
Exports
ordinal name
          ??abcfunc@@@QAE@ABV01@@Z (public: __thiscall abcfunc())
              :
          ??targetfunc@....

探したい関数がtargetfuncだったとすると、それが含まれるlibファイルはmaincore300.libということになります。

Summer Pockets(サマーポケッツ) 島モンファイト エサと場所で入手できる島モン組み合わせ一覧

発売日に予約していたものの時間が取れず、積んでおりました。昨日クリアしました…。

いや、大変よかったですね!各所でボロボロ泣きました。
特に後半は泣きすぎてマウスがクリックできなかったほど。

今回は個別ルート含め全体的にレベルが高い!
だーまえは原案だけということでちょっと心配でしたが、杞憂に終わりました。よかったよかった。

ただちょっと短かったかなぁ。
後半もうちょっとガッツリ作ってくれれば大満足でした。とりあえずファンディスク期待。

って、ちがう!!

この記事は島モンファイトの攻略記事です!
感想を書いてる場合じゃない!

島モンファイトはゲーム内のミニゲームで島モンを集めて、島の人たちとバトルをするもので、
まぁなんていうかポ○モンみたいなものです。いちおう専用のエンディングがあったりします。

ここでは島モンファイトについて、筆者が確認した範囲で情報をまとめたいと思います。
島モンは、同じ場所・同じエサの組み合わせでも複数候補の中からランダムに入手されるので、これで全部ということはありません。

たぶんREFLECTION BLUE版も同じと思われます。色々間違ってたらごめんネ。



島モンルートへの入り方

7/29にうみちゃんのアイコンを選択し、選択肢「うみちゃんと同じ物を1つ」を選ぶ→その後「参加を決める」を選ぶ。



エサ一覧と入手方法

エサ名 エサの入手方法
砂糖水(★1) 初回島モン開始時にうみちゃんがくれる
イカの皮(★1) 初回島モン開始時にうみちゃんがくれる
ミミズ(★1) 初回島モン開始時にうみちゃんがくれる
アイスの棒(★1) 初回島モン開始時にうみちゃんがくれる
昆虫ゼリー(★1) 島モンファイトで天善に勝利するともらえる
かき氷のシロップ(★2) 秘密基地に通い続ける。7/31にもらえる
ナスビ(★2) 島モンファイトで主婦を全員撃破
ユムシ(★2) 島モンファイトで漁師、おっさんを全員撃破
鰹節(★2) 島モンファイトで亀、犬、猫を撃破
島産蜂蜜(★3) 7/29の秘密基地の蜂退治のイベントで「頼んだぞ、良一!」「お前ならやれる、天善!」「俺が行くしかないだろう!」の3つの選択肢すべてを閲覧しているとイベント後に入手できる
ちょっとHな本(★3) 7/30に蒼ルートを選び、その後の宝探し中に秘密基地を選択する
失敗したチャーハン(★3) 料理ができなくなっている8位のうみちゃんに勝利する。
シーウッキー(★3) 駄菓子屋のガチャガチャで取得
米氷飴(★4) 駄菓子屋で8/2までに1回はガチャをし、8/3の選択肢で「ガチャしない」を選ぶ。
魚肉ソーセージ(★4) 島モンファイトで少年、少女を全員撃破
すごくHな本(★4) 島モンファイトで蒼に勝利する。
究極のチャーハン(★4) チュートリアルでうみちゃんに勝利し、その後8位のパワーアップしたうみちゃんに勝利する。
賢者になれるHな本(★5) 秘密基地に通い続ける。8/7にもらえる
稀少焼酎・もりいいぞう(★5) 駄菓子屋に通い続ける。8/7にもらえる
うみのパンツ(★5) 神社に通い続ける。選択肢に100円があれば、必ず100円を選ぶ→願い事を聞かれたら「卓球うまくなりたい」→イナリが出たときは50円→1000円の選択肢があれば1000円を選ぶ→その後も100円をお賽銭し続ける。8/7にもらえる。(島モンチュートリアルのときのうみちゃんのセリフが変化する)



エサと場所で入手できる島モン組み合わせ一覧

なんとなく属性がわかりづらいな〜と思った島モンは後ろに属性を記載してます。

エサ\場所  山のなか(★1) 浜辺(★1) ため池(★1) 山の奥(★2) 海岸(★2) 神社(★3) 山の最奥(★3) 絶壁(★4) 海賊の洞窟(★4) 秘境(★5)
砂糖水(★1) クロオオアリ(★1) カメノテ(★1) シオマネキ(★1) ヤマトシジミ(★1) ヤマトシジミ(★1) マメハチドリ(★3) ハナカマキリ(★2) リュウグウノツカイ(★3) リュウグウノツカイ(★3) タヌキ(★2)
イカの皮(★1) トノサマバッタ(★1) マダコ(★1) イカナゴ(★1) アブラゼミ(★1) アカボシゴマダラ(★1) ユリカモメ(★2) ミヤマクワガタ(★2) エチゼンクラゲ(★3) ダイオウイカ(★3) エチゼンクラゲ(★3)
ミミズ(★1) オケラ(★1) アメリカザリガニ(★1) コカマキリ(★1) ニホンヤモリ(★1) アブラゼミ(★1) イワツバメ(★2) アオダイショウ(★2) ピラルク(★3) リュウグウノツカイ(★3) ピラルク(★3)
アイスの棒(★1) アオカナブン(★1) アサリ(★1) ヒグラシ(★1) ハエトリグモ(★1) クマンバチ(★1) 17年ゼミ(★3) タヌキ(★2) ダイオウイカ(★3) ダイオウイカ(★3) 17年ゼミ(★3)
昆虫ゼリー(★1) エンマコオロギ(★1) ミズクラゲ(★1) クマンバチ(★1) アゲハチョウ(★1) ミドリガメ(★1) モルフォチョウ(★2) オンブバッタ(★1) リュウグウノツカイ(★3) リュウグウノツカイ(★3) ヒッコリーホーンドデビル(★3)
かき氷のシロップ(★2) クマンバチ(★1) クマンバチ(★1) ツクシガモ(★2) ミヤマクワガタ(★2) カメノテ(★1)[海] ミヤマクワガタ(★2) アオダイショウ(★2) ヒッコリーホーンドデビル(★3) ヒッコリーホーンドデビル(★3) ケツァルコアトル(★4)
ナスビ(★2) アカボシゴマダラ(★1) カラバガニ(★2) カメムシ(★1) アライグマ(★2) ニホンミツバチ(★1) ケンランカマキリ(★2) ミヤマクワガタ(★2) アレキサンドラトリバネアゲハ(★3) エチゼンクラゲ(★3) ヤタガラス(★4)
ユムシ(★2) キジバト(★1) ヒヨドリ(★1) ライギョ(★2) ニホンカナヘビ(★2) マガモ(★2) マメハチドリ(★3) アライグマ(★2) リュウグウノツカイ(★3) ピラルク(★3) 朱雀(★5)[空]
鰹節(★2) ツクツクボウシ(★1) カラスアゲハ(★1) ツクツクボウシ(★1) ニホンカナヘビ(★2) ユリカモメ(★2) アライグマ(★2) オニヤンマ(★2) ピラルク(★3) ダイオウイカ(★3) ダイオウイカ(★3)
島産蜂蜜(★3) オオスズメバチ(★2) プラナリア(★2) 17年ゼミ(★3) タヌキ(★2) 人魚(★4) 17年ゼミ(★3)、テンゼン(★4)[空] チュパカブラ(★4) マメハチドリ(★3) ギラファノコギリクワガタ(★3) ヘラクレスオオカブト(★3)
ちょっとHな本(★3) イナリ(★4) プラナリア(★2) テンゼン(★4)[空] オオカマキリ(★2) ラブカ(★4) テイオウムカシヤンマ(★3) ニホンオオカミ(★4) ダイオウイカ(★3) ヘラクレスオオカブト(★3) エチゼンクラゲ(★3)
失敗したチャーハン(★3) オケラ(★1)、ヘラクレスオオカブト(★3) 国産ウナギ(★2) コウモリ(★2) イナリ(★4)、ミヤマクワガタ(★2)、アレキサンドラトリバネアゲハ(★3) コウモリ(★2)、エンゼルフィッシュ(★2) ケツァルコアトル(★4) ジュエルキャタピラー(★3)、ギラファノコギリクワガタ(希少種)(★3) リュウグウノツカイ(★3)、シロハヤブサ(希少種)(★3) リュウグウノツカイ(★3) 17年ゼミ(★3)、ヘラクレスオオカブト(★3)
シーウッキー(★3) ツクシガモ(★2) ハリセンボン(★2)、ダイオウイカ(★3) 国産ウナギ(★2) アライグマ(★2)、シロハヤブサ(★3) オオスズメバチ(★2)、ハリセンボン(★2)、ラブカ(★4) テンゼン(★4) 白虎(★5)、イナリ(★4) オオシャコガイ(★3)、17年ゼミ(★3)、ケツァルコアトル(★4) オオシャコガイ(★3)、エチゼンクラゲ(★3) オオシャコガイ(★3)
米氷飴(★4) ジュエルキャタピラー(★3) ラブカ(★4) オニヤンマ(★2) ジュエルキャタピラー(★3) オオシャコガイ(★3) ヤタガラス(★4) ギラファノコギリクワガタ(★3) リュウグウノツカイ(★3) リュウグウノツカイ(★3) テイオウムカシヤンマ(★3)
魚肉ソーセージ(★4) チュパカブラ(★4) クマゼミ(★2) オオシャコガイ(★3) ヒッコリーホーンドデビル(★3) アレキサンドラトリバネアゲハ(★3) テンゼン(★4) ヒッコリーホーンドデビル(★3) シロハヤブサ(★3) ケツァルコアトル(★4)[空] ヤタガラス(★4)
すごくHな本(★4) 17年ゼミ(★3) ピラルク(★3)、テイオウムカシヤンマ(★3) エチゼンクラゲ(★3) テイオウムカシヤンマ(★3) クマゼミ(★2)、タラバガニ(★2)、ヌシ(★4) 朱雀(★5)[空] アレキサンドラトリバネアゲハ(★3) ライギョ(★2)、ヤタガラス(★4) ダイオウイカ(★3) ニホンオオカミ(★4)、テンゼン(★4)、ケツァルコアトル(★4)[空]
究極のチャーハン(★4) ホンノウサギ(★2)、ケツァルコアトル(★4) リュウグウノツカイ(★3) クリオネ(★2)、ヤタガラス(★4) アレキサンドラトリバネアゲハ(★3)、ニホンオオカミ(★4) タラバガニ(★2)、エチゼンクラゲ(★3) ケツァルコアトル(★4) アルマジロトカゲ(★3)、シロハヤブサ(★3) イナリ(★4) ピラルク(★3) リュウグウノツカイ(★3)
賢者になれるHな本(★5) テンゼン(★4)[空] ユリカモメ(★2) ピラルク(★3) シロハヤブサ(★3) リョウイチ(★4) シロハヤブサ(★3) アレキサンドラトリバネアゲハ(★3) アルマジロトカゲ(★3) ヌシ(★4) ヤタガラス(★4)
稀少焼酎・もりいいぞう(★5) アルマジロトカゲ(★3) リョウイチ(★4) ヌシ(★4) マメハチドリ(★3) オオシャコガイ(★3) 朱雀(★5)[空] 白虎(★5)[山] 青龍(★5)[海] ラブカ(★4) オニヤンマ(★2)
うみのパンツ(★5) アルマジロトカゲ(★3)、17年ゼミ(★3) 人魚(★4) 玄武(★5)[海] テンゼン(★4)[空] シロハヤブサ(★3)、ダイオウイカ(★3) テンゼン(★4) チュパカブラ(★4)[山] ヤシガニ(★2)、ニホンオオカミ(★4) テイオウムカシヤンマ(★3)、人魚(★4) ニホンオオカミ(★4)

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" }
}

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 PiのOSインストール中にエラーが起こったりと、なかなかうまくいきませんでした。

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

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

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

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

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

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

その1

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

その2

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

その3

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

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

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

小学校自体のメモはこれ。意外に綺麗ですね。

スキルポイント自動振り分け for DQX オンラインマニュアル (ver 1.4.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つの画面から構成されています。
以下、各画面について説明します。

最新(1.4.1)の更新内容 (2019/07/02にリリース)

  • 公式Web(広場)からスキルポイント自動取得機能において、レベル110まで取得出来るようにしました
  • スキル選択機能にて、スキルポイント190, 200を使用するスキルに対応しました
  • 遊び人のスキルテーブルに誤りがあったため修正しました。

前回(1.4.0)の更新内容(2019/04/30にリリース)

  • 職業「遊び人」および、スキル「あそび」を追加
  • 公式Web(広場)からスキルポイント自動取得機能において、レベル108まで取得出来るようにしました
  • 広場からの情報取得アルゴリズム改善

職業画面

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

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

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

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

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

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

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

その他の機能

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

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


スキル画面

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

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

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

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


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

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

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

パッシブスキル設定機能

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

その他の機能

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

スキル選択画面

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

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

パッシブスキル設定画面

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

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

結果画面

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

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

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

  • 魔法使いのもっているスキルポイント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ポイント不足していて、割り当てられなかった
注意:マスタースキルポイントの使用有無で表記を分けている理由

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

今後の予定

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

  • アルゴリズムの改善(適宜)
  • 高速化(適宜)
  • バグ修正(適宜)
  • 新職業/新スキル追加(適宜)
  • 結果画面のわかりやすさ改善(適宜)

Private Policy

taiyakisun built the スキルポイント自動振り分け for DQX app as a Free app. This SERVICE is provided by taiyakisun at no cost and is intended for use as is.

This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.

If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy.

The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at スキルポイント自動振り分け for DQX unless otherwise defined in this Privacy Policy.

Information Collection and Use

For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information. The information that I request will be retained on your device and is not collected by me in any way.

The app does use third party services that may collect information used to identify you.

Link to privacy policy of third party service providers used by the app

Log Data

I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics.

Cookies

Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.

This Service does not use these “cookies” explicitly. However, the app may use third party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.

Service Providers

I may employ third-party companies and individuals due to the following reasons:

To facilitate our Service;
To provide the Service on our behalf;
To perform Service-related services; or
To assist us in analyzing how our Service is used.
I want to inform users of this Service that these third parties have access to your Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.

Security

I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.

Links to Other Sites

This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.

Children’s Privacy

These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do necessary actions.

Changes to This Privacy Policy

I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately after they are posted on this page.

Contact Us

If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at ichimonji.factory@gmail.com.

This privacy policy page was created at privacypolicytemplate.net and modified/generated by App Privacy Policy Generator

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

はじめに

ノード間でTCP/IPおよびUDP/IP通信が通るかどうかをチェックするツールです。

  • 1つの実行ファイルにサーバー/クライアント両方の機能が入っているので、双方向の確認が可能です。
  • WindowsLinux両方でビルドできるので、プラットフォームを越えてのチェックが可能です。

注意事項はこちらです。

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

ビルド

Windows
  • Visual Studio Community 2015以降で動作確認済みです。
  • 追加のライブラリとして「ws2_32.lib」を追加しといてください。(プロジェクトのプロパティ→リンカー→入力→追加の依存ファイル)
  • 「WIN32」というマクロを定義しておいてください。(プロジェクトのプロパティ→C/C++プリプロセッサプリプロセッサの定義) ※昔はデフォルトで定義されてたのに、最近のはないんですね…
  • SDLが有効な場合は、無効にしてください。(プロジェクトのプロパティ→C/C++→全般→SDLチェックを「いいえ」にする)

あとは普通にビルド一発です。

Linux

gcc 4.8.5, 8.3.1(Redhat系), 9.3.0(Ubuntu)で動作確認済みです。
まぁ何でも適当で大丈夫だと思います。以下を実行してください。

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

以下のようなエラーが出た場合は、追加パッケージをインストールしてください。

  • Redhat系の場合は「gcc-c++」パッケージ (yum install gcc-c++)
  • Ubuntuの場合は「g++」パッケージ (sudo apt-get install g++) ※gccとg++のバージョンは合わせる必要があるようです。
gcc: error trying to exec 'cc1plus': execvp: そのようなファイルやディレクトリはありません

使用方法

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

■例
./main server tcp 192.168.1.10 19876
クライアント
実行ファイル client <プロトコル種別> <接続先IPアドレス> <接続先ポート> <接続元IPアドレス> <接続元ポート> <サーバーに送るメッセージ>

■例
./main client tcp 192.168.1.10 19876 0 0 ahanufun

※接続元のIPアドレスやポート番号に0を指定すると、OS(プロトコルスタック)が自動で選んだIPアドレス/ポート番号が選ばれます。

ソースコード (ここをコピペすべし!)

#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
{
    eNodeTypeUnknown = 0,
    eServer,
    eClient
};

static const char* NODE_SERVER = "server";
static const char* NODE_CLIENT = "client";

/* TCPかUDPの種別列挙子 */
enum ProtocolType
{
    eProtocolTypeUnknown = 0,
    eProtocolTCP,
    eProtocolUDP
};

static const char* PROTOCOL_TCP = "tcp";
static const char* PROTOCOL_UDP = "udp";


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

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


/* 受信関数。TCPの場合だけ使われます。 */
#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
}


void printUsage()
{
    printf("Usage:\n");
    printf("   server {tcp|udp} listening_addr listening_port\n");
    printf("   or\n");
    printf("   client {tcp|udp} dest_addr dest_port src_addr src_port message\n");
    printf("\n");
    printf("Example:\n");
    printf("   1. server tcp 192.168.1.5 12345\n");
    printf("      client tcp 192.168.1.5 12345 0 0 sample_to_12345\n");
    printf("\n");
    printf("   2. server udp 192.168.1.5 12345\n");
    printf("      client udp 192.168.1.5 12345 192.168.1.2 5000 sample_from_5000_to_12345\n");
}


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

    NodeType eNodeType = eNodeTypeUnknown;

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

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

        if (argc != 8)
        {
            fprintf(stderr, "Error: Bad args num(Client)(%d).\n", argc);
            printUsage();
            return 1;
        }
    }
    else
    {
        fprintf(stderr, "Error: Input correct NodeType(server or client).\n");
        printUsage();
        return 2;
    }


    ProtocolType eProtocolType = eProtocolTypeUnknown;

    if (strcmp(argv[2], PROTOCOL_TCP) == 0)
    {
        eProtocolType = eProtocolTCP;
    }
    else if (strcmp(argv[2], PROTOCOL_UDP) == 0)
    {
        eProtocolType = eProtocolUDP;
    }
    else
    {
        fprintf(stderr, "Error: Input correct ProtocolType(tcp or udp).\n");
        printUsage();
        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]:リッスンアドレス */
        /* [4]:リッスンポート   */

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


        /* リッスンソケットの作成 */
        netInfo.sock0 = socket(AF_INET, (eProtocolType == eProtocolTCP) ? SOCK_STREAM : SOCK_DGRAM, 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;
        }


        /** TCPの場合だけリッスンする */
        if (eProtocolType == eProtocolTCP)
        {
            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)
        {
            struct sockaddr_in  client = { 0 };
            SOCKLEN_TYPE        nClientLen = sizeof(client);
            
            if (eProtocolType == eProtocolTCP)
            {
                int sock = INVALID_SOCKET;

                /** TCPの場合だけacceptで待ち受けする */
                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;
                }

                /* TCPの場合、acceptと受信処理は分離したいため、受信用スレッドを立ち上げる */
                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
            {
                /** UDPの場合、acceptがないため、recvでブロッキングするような処理にする */
                char  inbuf[2048];   /* 受信バッファ     */
                char  atimeWk[64];   /* 時刻表示ワーク用 */

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

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

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

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


        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, (eProtocolType == eProtocolTCP) ? SOCK_STREAM : SOCK_DGRAM, 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;
        }


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


        if (eProtocolType == eProtocolTCP)
        {
            /** TCPの場合だけ、コネクションを確立させる */
            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;
            }

            (void)send(sock, sendmsg, (int)strlen(sendmsg), 0);
        }
        else
        {
            /** UDPの場合はsendtoするだけ */
            (void)sendto(sock, sendmsg, (int)strlen(sendmsg), 0, (struct sockaddr *)&netInfo.addr, sizeof(netInfo.addr));
        }

        SAFE_SOCK_CLOSE(sock);
    }


    return 0;
}
プライバシーポリシー お問い合わせ