質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++/CLI

C++/CLIは、.NET Frameworkの共通言語基盤であるCLI向けにC++を拡張したプログラム言語です。前身のC++マネージ拡張と比較するとシンプルで分かりやすい構文になっており、高い可読性を持ちます。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

3395閲覧

ネットワーク通信(TCP/IP)でコマンドの送受信をしようとしていますが、listen関数で発生するエラーの解決方法を探しています。

aacc

総合スコア7

C++/CLI

C++/CLIは、.NET Frameworkの共通言語基盤であるCLI向けにC++を拡張したプログラム言語です。前身のC++マネージ拡張と比較するとシンプルで分かりやすい構文になっており、高い可読性を持ちます。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/04/16 08:04

前提・実現したいこと

PC-PC間でネットワーク通信(TCP)で、
コマンドの送受信をするプログラムをVisual C++にて作成しようとしています。
ネットでの調査より、ソケット通信により実現可能と考え、
色々なリンク先を参考に、ソフトを作成しています。
現在、自PCから自PCに向けてコマンドを送ることで動作確認をしようとしており、
(クライアント側ではなく)サーバー側のプログラムの動作確認中です。
実行すると、listen関数でエラーが発生しており、
どうすればエラーが出ないようになるかが分かっておらず、
解決方法を知りたい次第です。

発生している問題・エラーメッセージ

以下のソースのlisten(sock, SOMAXCONN); のところでエラー10022が発生しています。 調べたところ、「パラメータはbind関数でバインドされていません。」なのだそうですが、 bind関数実行後のWSAGetLastError()では0となっており、バインドされているという認識でいます。

該当のソースコード

Visual

1 int ret; 2 SOCKET sock, sock2; 3 struct sockaddr_in sinme; 4 struct sockaddr_in from; 5 int len = sizeof(from); 6 int one = 1; 7 short port = 10001; 8 char message[1024]; 9 WSADATA wsaData; 10 11 ret = WSAStartup(MAKEWORD(2, 0), &wsaData); 12 if (ret != 0) { 13 printf("initialize error\n"); 14 } 15 16 sock = socket(AF_INET, SOCK_STREAM, 0); 17 18 sinme.sin_family = AF_INET; 19 sinme.sin_port = htons(port); 20 sinme.sin_addr.S_un.S_addr = htonl(INADDR_ANY); 21 22// setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes)); 23 24 bind(sock, (struct sockaddr *)&sinme, sizeof(sinme)); 25 ret = WSAGetLastError(); 26 if (ret != 0) { 27 printf("bind error : %d\n", WSAGetLastError()); 28 return; 29 } 30 31 ret = listen(sock, SOMAXCONN); 32 if (ret != 0) { 33 printf("listen error : %d\n", WSAGetLastError()); 34 return; 35 } 36 37 //接続要求待ち 38 printf("Waiting for Connection Request.\n"); 39 sock2 = accept(sock, (struct sockaddr *)&from, &len); 40 if (sock2 < 0 ) { 41 printf("Can’t accepted.\n"); 42 exit(0); 43 } else { 44 printf("Connected from %s.\n",inet_ntoa(from.sin_addr)); 45 } 46 47 //ソケットからのデータ待ち 48 recv(sock2, message, 1024, 0); 49 printf("Received Message=%s\n",message); 50 close(sock);//切断処理

試したこと

関係あるのか分かりませんが、ファイアウォールを無効にしてみましたが、
結果に変化はありませんでした。

補足情報(FW/ツールのバージョンなど)

●環境
windows 10 Professional 64bit
visual C++ 2017

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2020/04/16 09:02

とりあえず、bindの返り値を見ましょう。
dodox86

2020/04/16 09:38

WSAGetLastErrorは一般的に、直前のWinSock関連APIがNGだったときに使います。ですのでbindがNGの場合にのみ、有効なエラーコードを得られます。したがってotnさんのアドバイスをまず実践すべきです。>質問者さん
dodox86

2020/04/16 10:25

> エラー10022が発生しています。 > 調べたところ、「パラメータはbind関数でバインドされていません。」なのだそうですが、 10022は「WSAEINVAL, Invalid argument."無効な引数"」です。 https://docs.microsoft.com/ja-jp/windows/win32/winsock/windows-sockets-error-codes-2 「パラメータはbind関数でバインドされていません。」は少し意味合いが違いますね。
dodox86

2020/04/16 18:18

ふと気が付きましたが、タグに「C++/CLI」がついていますが、C++/CLIは使っていないですよね? そうであればタグを外してください。C++/CLIは ネイティブのC++とは別物です。
aacc

2020/04/16 23:41

コメントありがとうございます。 説明不足で申し訳ありません。 既存ソフトに本機能を追加したかったため、 元々はVisual C++ 2010のC++/CLIで作成したものを変換してVisual C++ 2017上で 使用している状態になります。 なので、C++/CLIのタグをつけていますが、認識として間違っていますでしょうか。 正直あまり分かっていません。申し訳ありません。
dodox86

2020/04/16 23:52 編集

> 元々はVisual C++ 2010のC++/CLIで作成したものを変換してVisual C++ 2017上で使用している状態になります。 > なので、C++/CLIのタグをつけていますが、認識として間違っていますでしょうか。 うーん、どうなんでしょう。もともとはC++/CLIのプロジェクトでビルドしていたものを変換しているので何か悪影響が出ているかもしれません。C++/CLIは動作基盤が.NET Frameworkです。私自身はそのようなやり方は(危険と思うので)したことが無いので、ちょっと影響が分かりません。 ということはご提示のコードは全体のごく一部なのでしょうか。TCP/IP, WinSockのプログラミングに不慣れならば尚更、Visual Studio 2017で新しくプロジェクトを作って、最低限のコードでまず意図通り動くのを確認することをお勧めします。
aacc

2020/04/17 04:23

コメントありがとうございます。 切り分けのためにも、御提案頂いたように、新規にVisual Studio 2017で作成したものでトライしてみようと思います。
aacc

2020/04/19 23:30

御提案頂いたように、Visual Stdio 2017で新規に作成したものだと、正常に動作するようになりました。 やはり2010からの変換だと何かと影響があるようです。 ありがとうございました。
guest

回答3

0

ベストアンサー

この質問で出ている現象と同件じゃないですか?

https://teratail.com/questions/168631

投稿2020/04/18 07:53

TaroToyotomi

総合スコア1449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2020/04/18 08:00

std::bindでの問題プラスC++/CLIのプロジェクトからの移行だとしたら、ちょっとむちゃくちゃですね。 (using namespace std とかどこかでやっていたら収拾つかなくなりそうです)
TaroToyotomi

2020/04/19 15:14

::bind(sock, (struct sockaddr *)&sinme, sizeof(sinme)); みたいにグローバルスコープでbind関数を実行してみたらうまくいくかもしれませんね。
aacc

2020/04/19 23:33

Taroさん リンク先ありがとうございます。 「using namespace std;」をコメントアウトすることで、 ret = bind...の記述もエラーが出なくなり、正常に動作(接続待ち)になるようになりました。 ありがとうございました。
guest

0

直接の解決につながる回答ではありません:

私の方でもご提示のコードをもとに動作確認してみましたが、残念ながら問題は再現しませんでした。listenで意図通りクライアントからの接続待ち受け状態になります。
(当方のSDKバージョンの都合もあり、Windows 10 Pro.(1903) 上でVisual Studio 2015を使いました)

bind(sock, (struct sockaddr *)&sinme, sizeof(sinme));のパラメータにゴミが混ざってしまって実は正しくbindできていなかったとか、IPv6とか、そういう問題でも無さそうに思います。

ご提案としてですが、問題切り分けの為にマイクロソフト提供のWinSockサーバーサンプルコードと照らして動作確認してみることをお勧めします。
Complete Winsock Server Code - Microsoft Docs

尚、本質問とは直接関係ないですがWinSockの場合、ソケットのクローズにはcloseではなくclosesocketを使います。その他、上記サンプルと見比べると足りない部分が分かるかと思います。

投稿2020/04/16 18:11

dodox86

総合スコア9256

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ご質問の回答には至っていませんが、ご参考まで。

ソースコードが一部しか記載されていないので、私の憶測で補完して実行してみました。
憶測が入っているのでなんらかの間違いがあるかもしれませんが、
私の環境ではとりあえず、ご質問でエラーとなっている listen() 関数はエラーなしで終わり、接続の確立とデータの受信はできたようです。
通信内容はまだかなり怪しいですが、ご質問の要点(listen() 関数のエラー)とは無関係なので、この状態で報告させていただきます。

環境は Windows10, VIsualStudio2019 です。

C++

1#include <stdio.h> 2#include <winsock2.h> 3#include <ws2tcpip.h> 4#pragma comment(lib, "Ws2_32.lib") 5 6void main() 7{ 8 int ret; 9 SOCKET sock, sock2; 10 struct sockaddr_in sinme; 11 struct sockaddr_in from; 12 int len = sizeof(from); 13 int one = 1; 14 short port = 10001; 15 char message[1024]; 16 WSADATA wsaData; 17 18 ret = WSAStartup(MAKEWORD(2, 0), &wsaData); 19 if (ret != 0) { 20 printf("initialize error\n"); 21 } 22 23 sock = socket(AF_INET, SOCK_STREAM, 0); 24 25 sinme.sin_family = AF_INET; 26 sinme.sin_port = htons(port); 27 sinme.sin_addr.S_un.S_addr = htonl(INADDR_ANY); 28 29 // setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes)); 30 31 ret = bind(sock, (struct sockaddr*) & sinme, sizeof(sinme)); 32 printf("bind() return %d\n", ret ); 33 ret = WSAGetLastError(); 34 if (ret != 0) { 35 printf("bind error : %d\n", WSAGetLastError()); 36 return; 37 } 38 39 ret = listen(sock, SOMAXCONN); 40 if (ret != 0) { 41 printf("listen error : %d\n", WSAGetLastError()); 42 return; 43 } 44 45 //接続要求待ち 46 printf("Waiting for Connection Request.\n"); 47 sock2 = accept(sock, (struct sockaddr*) & from, &len); 48 if (sock2 < 0) { 49 printf("Can’t accepted.\n"); 50 exit(0); 51 } 52 else { 53// printf("Connected from %s.\n", inet_ntoa(from.sin_addr)); 54 printf("Connected from ???.\n"); 55 } 56 57 //ソケットからのデータ待ち 58 recv(sock2, message, 1024, 0); 59 printf("Received Message=%s\n", message); 60// close(sock);//切断処理 61 62}

実行結果は以下です。
wsl で telnet を使って接続を試みたところ一応つながったようです。

cmd

1C:\>.\ConsoleApplication2.exe 2bind() return 0 3Waiting for Connection Request. 4Connected from ???. 5Received Message= 6フフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフ'フフフフフフフフフフ 7 8C:\>

以下は wsl 側の実行結果です。
xxx.xxx.xxx.xxx は上記プログラムを実行したパソコンの IPアドレスです。

WSL

1$ telnet xxx.xxx.xxx.xxx 10001 2Trying xxx.xxx.xxx.xxx... 3Connected to xxx.xxx.xxx.xxx. 4Escape character is '^]'. 5 6Connection closed by foreign host. 7$

投稿2020/04/16 10:14

編集2020/04/16 13:31
kozuchi

総合スコア1193

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aacc

2020/04/17 01:00

コメントありがとうございます。 dodox86さんからも御指摘がありましたように、既存ソフトに本機能を追加したかったため、元々はVisual C++ 2010のC++/CLIで作成したものを変換してVisual C++ 2017上で使用している状態になります。 説明が不足しており、申し訳ありません。 記述頂いた内容で試してみましたが、変更前の状態と同様になります。(10022のエラー) bind関数についてお伺いしたいのですが、ret = bind(。。。のように記述すると、 ビルドエラーとなり以下が表示されます。 「'=': 'std::_Binder<std::_Unforced,SOCKET &,sockaddr *,size_t>' から 'int' に変換できません。」 冒頭の#include部はいかになります。 #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <ws2tcpip.h>         ←変更前には記述がなく御教授の元、追加したものです。 #pragma comment(lib, "Ws2_32.lib")  ←変更前には記述がなく御教授の元、追加したものです。
kozuchi

2020/04/17 04:46

ヘッダを変更して、VisualStudio2017 でコンパイルしてみると、 エラー (アクティブ) E1097 "no_init_all" は不明な属性です ConsoleApplication3 C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\winnt.h 7597 といったエラーが出ました。 調べたところ、VisualStudio2017 の旧版のバグらしいので、最新版に更新したところ、 回答に記載した内容と同様に動作しました。 更新後のバージョンは以下です。 Microsoft Visual Studio Community 2017 Version 15.9.22 VisualStudio.15.Release/15.9.22+28307.1093 Microsoft .NET Framework Version 4.8.03752
aacc

2020/04/19 23:40

kozuchiさん コメントありがとうございます。 バージョンよる影響もあるんですね。 今回は他の方々のコメントにより解決に至っておりますが、 今後のソフト作成にバージョンによる影響も考慮したいと思います。 色々と情報を頂き、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問