WinSockでの通信プログラムがうまくいきません。
使用言語はC++とDirectXです。
ローカルでの通信(ルータを介したパソコン同士)はうまくいくんですが、別の場所にあるPCとの通信ができません。
以下実際に使用している関数です。
関数はマルチスレッドで動かしています。
WSADATA mWsaData;
SOCKET mSockYou,mSockI;
struct sockaddr_in mAddr;
struct sockaddr_in mServer;
struct sockaddr_in mClient;
void CNetwork::Init(){
int err = WSAStartup( MAKEWORD( 2, 0 ), &mWsaData );
if( err != 0 ){
ERROR_EXIT();
return;
}
//Socket初期化
mSockI = socket( AF_INET, SOCK_STREAM, 0 );
if( mSockI == INVALID_SOCKET ){
ERROR_EXIT();
return;
}
mPort = 0;
memset( mName, 0, sizeof( mName ) );
}
//Server側
void CNetwork::Accept(){
FILE* fp;
fopen_s( &fp, "messageLog.txt", "w" );
mAddr.sin_family = AF_INET;
mAddr.sin_port = htons( mPort );
mAddr.sin_addr.S_un.S_addr = INADDR_ANY;
if( bind( mSockI, (struct sockaddr *)&mAddr, sizeof( mAddr ) ) ) fprintf_s( fp, "bind失敗\n" );
if( listen( mSockI, 10 ) != 0 ) fprintf_s( fp, "listen失敗\n" );
int len = sizeof( mClient );
SOCKET t = accept( mSockI, (struct sockaddr*)&mClient, &len );
if( t == INVALID_SOCKET ) fprintf_s( fp, "Accept失敗\n" );
mSockYou = t;
fprintf_s( fp, "Accept終了\n" );
fclose( fp );
}
void CNetwork::Connect(){
FILE* fp;
fopen_s( &fp, "messageLog.txt", "a" );
fprintf_s( fp, "Connect開始\n" );
//ソケットの設定
mServer.sin_family = AF_INET;
mServer.sin_port = htons( mPort );
mServer.sin_addr.S_un.S_addr = inet_addr( mName );
if (mServer.sin_addr.S_un.S_addr == 0xffffffff) {
fprintf_s( fp, "hostbynameへ\n" );
struct hostent *host;
host = gethostbyname( mName );
if ( host == NULL ) {
return false;
}
mServer.sin_addr.S_un.S_addr = *(unsigned int *)host->h_addr_list[0];
}
fprintf_s( fp, "Socketの設定完了\n" );
while( true ){
fprintf_s( fp, "connect()開始\n" );
if( connect( mSockI, (struct sockaddr *)&mServer, sizeof( mServer ) ) == 0 ){
fprintf_s( fp, "Connect完了\n" );
break;
}
else{
fprintf_s( fp, "Connect失敗\n" );
Sleep(100);
}
}
fprintf_s( fp, "Connect終了\n" );
fclose(fp);
}
また、ログは下のように出ました。
//サーバ側
Accept失敗
//クライアント側
Connect開始
Socketの設定完了
connect()開始
Connect失敗
ご教授お願いします。
A 回答 (10件)
- 最新から表示
- 回答順に表示
No.10
- 回答日時:
NO.9の者です。
もし複数ルーターで分断されたLAN同士の通信ということでなく、ルーターを一段介しただけのクライアント・サーバー間通信であればNATブレイクは必要ないのでプログラムのバグでしょう。
出来ればネットワーク構成と端末接続構成を知りたいですね。
No.9
- 回答日時:
あなたのプログラムを読んではいないのですが、もし実験しているPC群が複数のルータで分けられた複数LANに散在しているのであればNATブレイクの必要アリかと・・・
P2P通信には必須の方法です。
ルーターR0以下に構成されているLAN内にあるソケット同士は普通にソケット関数をたたいてやれば通信できますが、ルーターR0とルーターR1で別々のLANが構築されていて、どのルーターもブリッジモードにはなっていないという前提(ルートのルーターにカスケード接続されたルーターとして動いている)ならば、R0以下のPCとR1以下のPCがP2P通信するにはまずNATブレイクでしょうね。NATピンホールパンチなどとも呼びますか・・
No.8
- 回答日時:
エラーについて書き忘れです。
>これは、関数呼び出しの間に割り込みがあったとのことですが、
>そのような処理の原因として何か考えられるものはあるでしょうか?
>マルチスレッドにしたことが原因でしょうか?
>(一定時間ごとに呼び出されるため、いちいち中断している可能性もありますし)
WSAEINTRはWinsock1.1の停止型ソケットが
WSACancelBlockingCallで取り消されたときに
発生するエラーです。
この関数は、現在非推奨になっていて、
一般にWinsock2では外部公開されない関数です。
MSDNにはGUIスレッドから内部で呼び出される
可能性があると記載がありますので、
GUIを使用すると発生するという可能性があります。
対応策としては、非同期ソケットにする必要が
あるかもしれません。
No.7
- 回答日時:
反応が遅くなりましたが。
。。ちょこっと見てて気になったことを
書いておきます。
・socketの作成
プロトコルが0で指定されていますが、
環境によって値が変わってしまうので、
TCPならIPPROTO_TCPを指定した方がよさそう。
ちなみに手持ちの環境で、winsock1なら
0はIPPROTO_IP、IPPROTO_TCPは6に
なっています。
#VC2008環境。
・Bind対象のアドレス
一番気になったところですが、
サーバ側のソケットは意図した
アドレスにbindされていますか?
ListenSocketのアドレス情報が、
mAddr.sin_addr.S_un.S_addr = INADDR_ANY;
となっている為、意図したアドレスに
bindされていないような気がします。
#ちなみにInAddrを使用する方法は
#既に一般的ではありません。
・マルチスレッド
標準ライブラリ関数と、_beginthread
CreateThreadなどを併用すると
メモリリークが発生するという問題が
確か数年前にMSから出ていたと思います。
Windows上で標準関数とマルチスレッドを
使用する場合は_beginthreadex()
_endthreadex()を使いましょう。
・クライアントについて
クライアントで使用されているOSは何でしょうか?
WindowsVista以降の場合、IPv6のアドレスが
割り当てられている可能性もありますが、
上記のコードはIPv4環境でしか使用できません。
#IPv6とIPv4が両方割り当てられていれば大丈夫かも。
No.6
- 回答日時:
返却されるエラーについては不明になってしまいますな…。
より低レベルな部分で確認が必要なのかも知れません。
パーソナルファイヤーウォールで拒否はしていませんよね?
# 同一ネットワークの場合は無条件で受け入れ…とかになっているのかも知れませんし。
Wiresharkなどで接続要求が来ているか確認してみるのも必要かも知れません。
No.5
- 回答日時:
>クラス内の関数をマルチスレッドで動かすようにしています。
Connectも同様です。CNetwork::AcceptStart()の呼び出し元でインスタンスの破棄とかしていませんか?
# デストラクタのshutdown()とか走ったから、「WSACancelBlockingCall()でキャンセルを…」というエラーが返却されている…とか考えられませんかね?
というか…スレッドにしてもインスタンスを破棄する前に起動したスレッドを停止させないとなりませんよね?
accept()が動作しないと、TerminateThread()で無理矢理殺すことになるかと思われますが…。
# _beginthread()で生成したモノをTerminateThread()で…だと、リソースリークとかしそうな気がします。
>一定時間main関数(またはメッセージ処理)を行わないとフリーズして止まってしまうので、このような形でサブスレッドで実行するようにしてます。
select()または、WSAAsyncSelect()やWSAEventSelect()を使うべき…かと。
とはいえ、ローカルネットワークでは問題ない(表面化していないだけの可能性もありますが)が、別の場所(外部ネットワーク経由?)だとダメ…というのも……。
# ルータのポート転送関係はチェック済みなんですよね?当然。
この回答への補足
>インスタンスの破棄
インスタンスの破棄は、アプリケーション自体を閉じたときにしか呼び出していないのでおそらくないとは思います・・・
>ルータのポート転送関係
ポートの開放のことでしょうか?ポートの開放でしたら、お互いに開放は行っています。
No.4
- 回答日時:
>accept()は接続要求されるまでそこで待機されると思っていたので、connect()とのタイミングなどとの関係はあるのですか?
ブロッキングモードですので接続されるまで待つでしょうから、とりあえずは問題なさそうです。
# accept()がタイムアウト…なんてことはたぶん無いと思われますが。
サーバ側のマルチスレッド…はどのような動作になっているのでしょう?
呼び出し元のCNetwork::Accept()は接続されるまで戻ってきませんが、問題ない…んですよね?
# 戻らない…ので、そのクラスを別のスレッドから破棄することもできない…ハズです。
accept()で、エラーがWSAEINTRとなると…WSACancelBlockingCall()でキャンセルしろ…と?
この回答への補足
サーバ側の動作は以下のようにしています。
クラス内の関数をマルチスレッドで動かすようにしています。Connectも同様です。
void CNetwork::AcceptStart(){
mThread = (HANDLE) _beginthread(
&CNetwork::AcceptLauncher,
0,
this);
}
static void AcceptLauncher(void* args){
reinterpret_cast<CNetwork*>(args)->Accept();
}
DirectXの仕様なのか、一定時間main関数(またはメッセージ処理)を行わないとフリーズして止まってしまうので、このような形でサブスレッドで実行するようにしてます。
No.3
- 回答日時:
>accept関数の後、調べてみた結果WSAEINTRというエラーが発生していました。
listen()の直後にaccept()している様ですが…
ねそのタイミングでクライアントがconnect()していますか?
# ノンブロッキングでしょうから、タイムアウトまでaccept()で止まっているとは思われますが…。
複数接続できるようには作られていないっぽいので、listen()で10接続受け付ける様にするのは止めた方がいいかもしれません。
# まぁ、初回以外はaccept()されないのでクライアントはタイムアウトするでしょうが。
ということで、マルチスレッドにしても接続できるのは1クライアントだけです。
テストに使用した環境が接続保持状態のまま正しく開放できていなかったりしませんか?
CNetworkクラスがどうなっているのか、同じポートで複数のインスタンスを作っていないか(その場合、bind()失敗ですが)、デストラクタで正しくSocket()の開放が行われているか…等々確認されてはどうでしょうか?
参考URL:http://www.kt.rim.or.jp/~ksk/wskfaq-ja/
この回答への補足
>listen()の直後にaccept()している
accept()は接続要求されるまでそこで待機されると思っていたので、connect()とのタイミングなどとの関係はあるのですか?
>複数接続できるようには作られていない
はい、このプログラムでは1つだけ接続が確立できればいいです。その場合、listen()では1つだけ受け付けるようにすればいいのですか?
>テストに使用した環境が接続保持状態のまま正しく開放できていなかったりしませんか?
一応毎回CNetwork内のデストラクタで解放処理は行っています。
以下ソースコードです。
void CNetwork::Destroy(){
if( mType == TCP_SERVER ){
shutdown( mSockI, SD_BOTH );
closesocket( mSockYou );
}
//WinSock解放
WSACleanup();
ThreadClose();
DeleteCriticalSection( &mCSThread );
}
No.2
- 回答日時:
通信周りの関数で失敗した直後に
WSAGetLastError関数を使用して
エラーの詳細コードを取るとセッションが
確率できない理由がわかるかも知れません。
大抵の場合、ローカルエリアでつながるけど
インターネットでつなげないのは、
ポートの解放がうまく行ってない場合が多いです。
ポートの設定はお使いのルータによって異なるので
確認してみてください。
この回答への補足
accept関数の後、調べてみた結果WSAEINTRというエラーが発生していました。
これは、関数呼び出しの間に割り込みがあったとのことですが、そのような処理の原因として
何か考えられるものはあるでしょうか?
マルチスレッドにしたことが原因でしょうか?(一定時間ごとに呼び出されるため、いちいち中断している可能性もありますし)
No.1
- 回答日時:
ログの状況から見て、サーバー側のAccept失敗が問題だと感じます。
Acceptの失敗コードをとるのが良いのではないでしょうか?
ちなみにAcceptが失敗する理由は、
http://software.aufheben.info/kouza/senior/kouza …
を参照されると、良いかもしれません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- Excel(エクセル) VBA フォルダ見える化のコードについて 2 2023/06/19 15:04
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- Visual Basic(VBA) VBAの繰り返し処理について教えてください。 3 2022/08/02 13:21
- Ruby vscode 文字化け 1 2022/05/21 19:17
このQ&Aを見た人はこんなQ&Aも見ています
-
これまでで一番「情けなかったとき」はいつですか?
これまでの人生で一番「情けない」と感じていたときはいつですか? そこからどう変化していきましたか?
-
大人になっても苦手な食べ物、ありますか?
大人になっても、我慢してもどうしても食べれないほど苦手なものってありますよね。 あなたにとっての今でもどうしても苦手なものはなんですか?
-
遅刻の「言い訳」選手権
よく遅刻してしまうんです…… 「電車が遅延してしまい遅れました」 「歯医者さんが長引いて、、、」 「病院が混んでいて」 などなどみなさんがこれまで使ってきた遅刻の言い訳がたくさんあるのではないでしょうか?
-
いけず言葉しりとり
はんなりと心にダメージを与える「いけず言葉」でしりとりをしましょう。 「あ」あら〜しゃれた服着てはりますな 遠くからでもわかりましたわ
-
お風呂の温度、何℃にしてますか?
みなさん、家のお風呂って何℃で入ってますか? ぬるめのお湯にゆったり…という方もいれば、熱いのが好き!という方もいるかと思います。 我が家は平均的(?)な42℃設定なのですが、みなさんのご家庭では何℃に設定していますか?
-
ソケットの異常終了について
C言語・C++・C#
-
NetworkStreamからのRead()で、処理が止まる(C#)
C言語・C++・C#
-
Winsockで接続待ちタイムアウトを設定する方法
C言語・C++・C#
-
-
4
VB6のwinsockでconnectできない
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
TCP/IP通信時のサーバーからの受信
-
UDP通信におけるbind関数について
-
ソケット通信
-
UdpClient 送信元のIPアドレ...
-
Connectエラーが出てしまう・・...
-
recv関数でフリーズしてしまう
-
ソケットのrecvの戻り値が0
-
CreateFile関数でCOMポートが開...
-
UDPのソケットプログラミング
-
メールサーバへの接続タイムア...
-
TCP/IP通信型プログラムです。 ...
-
SIPがNATを越えられない理由
-
Socket通信の0バイト受信について
-
VC++でのソケット通信について
-
fsockopenのソケットが全然分か...
-
PerlでSocketを閉じずに再利用...
-
C言語のよるrsh-clientの簡潔...
-
ソケットでクライアントのipア...
-
VBとCでのソケット通信について
-
winsockを使った通信での同時接...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
TCP/IP通信時のサーバーからの受信
-
エクセル VBA でのCOMポート...
-
ソケットのrecvの戻り値が0
-
recv関数でフリーズしてしまう
-
VB6のwinsockでconnectできない
-
UDP通信する時に、相手にどうや...
-
UDP通信におけるbind関数について
-
ソケットでクライアントのipア...
-
Socket通信の0バイト受信について
-
ソケット通信 同じポート番号...
-
UdpClient 送信元のIPアドレ...
-
Winsockで接続待ちタイムアウト...
-
ソケットのクローズについて
-
ソケットを用いた1対多通信につ...
-
Connectエラーが出てしまう・・...
-
非ブロッキングソケットのrecv...
-
CreateFile関数でCOMポートが開...
-
Socket通信を待ち受け状態にす...
-
同じLAN内パソコンのIPアドレス...
-
WinSockでの通信プログラムがう...
おすすめ情報