私のアプリケーションのサーバー部分で作業していますが、私は解決できないような問題に遭遇しました。次のようにConnectionManager
クラスの一部であるサーバの初期化関数は、である。ソケットプログラミング:listen()でエラーが発生しました
int ConnectionManager::init_server() {
// Log
OutputDebugString(L"> Initializing server...\n");
// Initialize winsock
WSAData wsa;
int code = WSAStartup(MAKEWORD(2, 2), &wsa);
if (code != 0) {
// Error initializing winsock
OutputDebugString(L"> Log: WSAStartup()\n");
output_error(code);
return -1;
}
// Get server information
struct addrinfo hints, *serverinfo, *ptr;
SOCKET sockfd = INVALID_SOCKET;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_protocol = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
if (getaddrinfo(NULL, PORT, &hints, &serverinfo) != 0) {
// Error when getting server address information
OutputDebugString(L"> Log: getaddrinfo()\n");
output_error(WSAGetLastError()); // Call Cleanup?
return -1;
}
for (ptr = serverinfo; ptr != NULL; ptr = ptr->ai_next) {
// Create socket
if ((sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol)) == INVALID_SOCKET) {
// Error when creating a socket
OutputDebugString(L"> Log: socket()\n");
output_error(WSAGetLastError()); // Call Cleanup?
continue;
}
// Set options
const char enable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == SOCKET_ERROR) {
// Error when setting options
OutputDebugString(L"> log: setsockopt()\n");
output_error(WSAGetLastError()); // call cleanup?
if (closesocket(sockfd) != 0) {
output_error(WSAGetLastError());
}
return -1;
}
// Bind socket
if (bind(sockfd, ptr->ai_addr, ptr->ai_addrlen) == SOCKET_ERROR) {
// Error on binding
OutputDebugString(L"> Log: bind()\n");
output_error(WSAGetLastError()); // Call Cleanup?
if (closesocket(sockfd) != 0) {
output_error(WSAGetLastError());
}
continue;
}
break;
}
freeaddrinfo(serverinfo);
if (ptr == NULL) {
OutputDebugString(L"Error: Failed to launch server.\n");
return -1;
}
// Listen
if (listen(sockfd, BACKLOG) == SOCKET_ERROR) {
OutputDebugString(L"> Log: listen()\n");
output_error(WSAGetLastError()); // Call Cleanup?;
return -1;
}
// Accept
struct sockaddr_storage clientinfo;
int size = sizeof(struct sockaddr_storage);
m_exchfd = accept(sockfd, (struct sockaddr *)&clientinfo, &size);
if (m_exchfd = INVALID_SOCKET) {
// Error when accepting
OutputDebugString(L"> Log: accept()\n");
output_error(WSAGetLastError()); // Call Cleanup?
if (closesocket(sockfd) != 0) {
output_error(WSAGetLastError());
}
return -1;
}
m_isConnected = true;
return 0;
}
output_error
機能は、単にメッセージが関数を使用してエラーに対応する印刷します。しかし、私は次のような出力が得られます。
> Log: listen()
> ERROR: The attempted operation is not supported for the type of object referenced.
したがって、誤差が混乱してlisten()
への呼び出しによって発生しなければなりません。誰が問題の原因を教えてくれますか?私はそれが何かを修正するのは簡単だろうと思うが、私はそれを見ていないようだ。
、おかげで彼らのために多くのことを、私はまだ同じ取得しますエラー、両方のアドレスが見つかりました。また、setsockopt()関数でBOOLを使う理由は何ですか?それのプロトタイプによれば、代わりにcharを使用すべきですか? –
'listen()'が失敗したときの 'ptr-> ai_family'、' ptr-> ai_socktype'、 'ptr-> ai_protocol'の実際の値は何ですか? 'AF_INET/6'、' SOCK_STREAM'、 'IPPROTO_TCP'でなければ何かが間違っています。ああ、待って、私はちょうどあなたのコードで別のエラーを見た。私は自分の答えを編集しました。 –
['setsockopt()'のドキュメントを読んでください(https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476.aspx)。 'SO_REUSEADDR'は' BOOL'を待ちます。 'setsockopt()'のシグネチャを 'char *'ポインタを使ってだましてはなりません(論理的には 'void *'を使うべきです)。それは歴史的な時からのキャリーオーバーです。実際にはどんな種類のポインタも取ることができます。型キャストする必要があります。他のいくつかのソケットAPI関数と同様に、とりわけ 'sockaddr *'ポインタを取ると宣言されていますが、 'sockaddr_XX *'ポインタを実際に取ることができます。 –