前提・実現したいこと
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
とりあえず、bindの返り値を見ましょう。
WSAGetLastErrorは一般的に、直前のWinSock関連APIがNGだったときに使います。ですのでbindがNGの場合にのみ、有効なエラーコードを得られます。したがってotnさんのアドバイスをまず実践すべきです。>質問者さん
> エラー10022が発生しています。
> 調べたところ、「パラメータはbind関数でバインドされていません。」なのだそうですが、
10022は「WSAEINVAL, Invalid argument."無効な引数"」です。
https://docs.microsoft.com/ja-jp/windows/win32/winsock/windows-sockets-error-codes-2
「パラメータはbind関数でバインドされていません。」は少し意味合いが違いますね。
失礼しました。listen異常終了の際のWSAGetLastError のWSAEINVALの意味においては、「パラメータはbind関数でバインドされていません。」で合っていますね。(私の指摘間違いです)
https://docs.microsoft.com/ja-jp/windows/win32/api/winsock2/nf-winsock2-listen?redirectedfrom=MSDN
> WSAEINVAL The socket has not been bound with bind.
ふと気が付きましたが、タグに「C++/CLI」がついていますが、C++/CLIは使っていないですよね? そうであればタグを外してください。C++/CLIは ネイティブのC++とは別物です。
コメントありがとうございます。
説明不足で申し訳ありません。
既存ソフトに本機能を追加したかったため、
元々はVisual C++ 2010のC++/CLIで作成したものを変換してVisual C++ 2017上で
使用している状態になります。
なので、C++/CLIのタグをつけていますが、認識として間違っていますでしょうか。
正直あまり分かっていません。申し訳ありません。
> 元々はVisual C++ 2010のC++/CLIで作成したものを変換してVisual C++ 2017上で使用している状態になります。
> なので、C++/CLIのタグをつけていますが、認識として間違っていますでしょうか。
うーん、どうなんでしょう。もともとはC++/CLIのプロジェクトでビルドしていたものを変換しているので何か悪影響が出ているかもしれません。C++/CLIは動作基盤が.NET Frameworkです。私自身はそのようなやり方は(危険と思うので)したことが無いので、ちょっと影響が分かりません。
ということはご提示のコードは全体のごく一部なのでしょうか。TCP/IP, WinSockのプログラミングに不慣れならば尚更、Visual Studio 2017で新しくプロジェクトを作って、最低限のコードでまず意図通り動くのを確認することをお勧めします。
コメントありがとうございます。
切り分けのためにも、御提案頂いたように、新規にVisual Studio 2017で作成したものでトライしてみようと思います。
御提案頂いたように、Visual Stdio 2017で新規に作成したものだと、正常に動作するようになりました。
やはり2010からの変換だと何かと影響があるようです。
ありがとうございました。
回答3件
あなたの回答
tips
プレビュー