C++ TCPの受信ループにつきまして

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
tonton

C++ TCPの受信ループにつきまして

#1

投稿記事 by tonton » 4ヶ月前

こんにちは。
とてもサイトが様変わりして驚いております。
(スレッド作成時の質問が難しい…)

コード:

std::map<int,int> clinetSockList;

// Clientの受け入れ待ちスレッド
int clinetSock = accept(serverSock, (struct sockaddr *)&client, &len);
clientSockList[count] = clientSock;

// 受信ループスレッド
iterator it = clientSockList.begin();

// 受け入れたClientの数だけRecvを呼んで、データが無いかをチェックする
while(it != clientSockList.end())
{
  //ノンブロック設定済み
  recv(*it);
  ++it
}
私は現在上記の様なコードでTCPの受信ループ処理を書いております。
この方法ではClientの数が1万人や10万人となった時に毎回その人数分ループが走り、非常に宜しくない事となります。
どうにかして必要最小限のRecvを呼びたいと考えておりますが、もし他に良い書き方が御座いましたらご教授頂けますと幸いです。
(出来ればパケットを受信しているSocketを的確に知りたい…)

もし上記のやり方が普通だよ、という事でしたら自信が持てるというか安心致します。
宜しくお願い致します。

アバター
にこよん
記事: 101
登録日時: 1年前
住所: 大阪府
連絡を取る:

Re: C++ TCPの受信ループにつきまして

#2

投稿記事 by にこよん » 4ヶ月前

すみません回答ではないです

私もwinsock2で通信しようとしているのですが、localhostでしか通信に成功しておらず、他PCからのIP検索では全く通信できていないです(クライアントからのconnect関数で失敗する)

質問に対してこのようなスレッドで申し訳ないのですが、差支えなければクラスなどのその通信ソースを見せていただけないでしょうか?m(__)m
最近は東方風アクションゲームを少しずつ作ってる人です
東方翠風燐FreeDownload⇒http://dxlib.o.oo7.jp/cgi/patio/read.cgi?no=212

YuO
記事: 914
登録日時: 7年前
住所: 東京都世田谷区

Re: C++ TCPの受信ループにつきまして

#3

投稿記事 by YuO » 4ヶ月前

tonton さんが書きました:
4ヶ月前
私は現在上記の様なコードでTCPの受信ループ処理を書いております。
この方法ではClientの数が1万人や10万人となった時に毎回その人数分ループが走り、非常に宜しくない事となります。
どうにかして必要最小限のRecvを呼びたいと考えておりますが、もし他に良い書き方が御座いましたらご教授頂けますと幸いです。
map<int, int>ということはunix系を利用している前提で良いでしょか。
オフトピック
WindowsだとソケットはSOCKET型を使うので
recv(std::pair<int,int>)の内容がよくわかりませんが,unix系だとselectを利用した非ブロッキングI/Oが基本かと。
ディスクリプタの配列を用意しておいて,selectして,FD_ISSETでイベントを確認する形です。
https://www.ibm.com/support/knowledgece ... nblock.htm

なお,10万のTCP接続を1つのIPアドレスで同時に処理することはできません (ポートが16bit分しかないため)。
10万の接続を受け入れたいのであれば,複数台で処理したり,TCPの接続時間を短くするなどの別の工夫が必要になります。

tonton

Re: C++ TCPの受信ループにつきまして

#4

投稿記事 by tonton » 4ヶ月前

>>にこよん様

パブリック(グローバル)IPで送受信出来ないという事であれば、にこよん様の記載された処理というよりはどちらかのPCのファイアーウォールあるいはルーターの設定が怪しいかと思われます。
問題の切り分けとして
①自分のPC、レンタルサーバーの送受信をテストしてみる
②レンタルサーバーを2台借りて、同じソースコードでレンタルサーバー同士の送受信を試してみる
(②で動作すればソースコードに問題は御座いません。

私もほとんどサンプルコードで御座いますし技術的にも稚拙で御座いますので、ここにいらっしゃる他の方々にお尋ね頂いた方が宜しいかと思われます。


>>Yuo様

ServerがLinux、ClientはWinで行っております。
Selectの仕様を勘違いしておりました。狙った挙動が実装出来そうです。

>なお,10万のTCP接続を1つのIPアドレスで同時に処理することはできません (ポートが16bit分しかないため)。
すっかり失念してしまっておりました。
ログイン等を管理するMasterServerを一台置いて、ゲーム処理を行うGameServerを増やしていき負荷分散を行う予定でしたが、考えを改める必要がありますね…。
RUDPを導入してみるなど少し根本から設計を見直してみます。

ご回答有難う御座いました。

アバター
にこよん
記事: 101
登録日時: 1年前
住所: 大阪府
連絡を取る:

Re: C++ TCPの受信ループにつきまして

#5

投稿記事 by にこよん » 4ヶ月前

このような質問にご回答いただきありがとうございます
確認方法のご教授ありがとうございましたm(__)m
参考にやってみようと思います
最近は東方風アクションゲームを少しずつ作ってる人です
東方翠風燐FreeDownload⇒http://dxlib.o.oo7.jp/cgi/patio/read.cgi?no=212

tonton

Re: C++ TCPの受信ループにつきまして

#6

投稿記事 by tonton » 4ヶ月前

>>Yuo様

ちょっと本日色々と眺めておりまして
http://d.hatena.ne.jp/ryousanngata/20091122/1258838710
こちらに記載されてます通り、selectを用いた場合であっても

コード:

// 各ソケットの状況チェック
			for(i=0; i<FD_SETSIZE; i++){
				if(accept_list[i] != -1 && FD_ISSET(accept_list[i], &fds)){
の様にFD_ISSETで全Socketをループさせて確認しなければならないという認識で正しいでしょうか?

そうなるとノンブロックのrecvを全ループさせるのと結局の所流れとしては同じなのでしょうかね。
処理負荷、処理時間の計測はしておりませんので、そうした面で有利という可能性はありますね。
宜しくお願い致します。

返信

“C言語何でも質問掲示板” へ戻る