I am trying to program a socket to listen to an incoming connection but it won't work. I can successfully bind to the socket but I can't listen to it.
Here is my code:
main.cpp:
int main()
{
const char* m_ipAddress;
WSAData wsData;
WORD ver = MAKEWORD(2,2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
return wsOk;
}
else
{
cout << "WSAStartup successful" << endl;
}
int m_socket = socket(AF_INET, SOCK_STREAM, 0);
if (m_socket == INVALID_SOCKET)
{
return WSAGetLastError();
}
else
{
cout << "Socket successfully initialized" << endl;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(800);
inet_pton(m_socket, m_ipAddress, &hint.sin_addr);
int nRet = bind(m_socket, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR;
if (nRet < 0)
{
cout << endl << "Fail to bind to local port";
WSACleanup();
exit(EXIT_FAILURE);
}
else
{
cout << endl << "Binding successful";
}
// The Problem is here, This is supposed to return
nRet = listen(m_socket, SOMAXCONN);
if (nRet < 0)
{
cout << endl << "Fail to listen to local port";
// The return value of nRet
cout << endl << "nRet is " << nRet << "\n";
WSACleanup();
exit(EXIT_FAILURE);
}
else
{
cout << endl << "Listening Successful: ";
}
return 0;
}
The Output:
WSAStartup successful
Socket successfully initialized
Binding successful
Fail to listen to local port
nRet is -1
I tried using the memset method instead of inet_pton but that had little to no effect.
There are some major issues with your code:
m_ipAddress
is uninitialized, causing undefined behavior when you call inet_pton()
.
your error handling of bind()
is wrong. You are comparing the return value of bind()
against SOCKET_ERROR
(which is ok), but you are assigning the boolean result of that comparison to nRet
, and then comparing that value against < 0
, which will always evaluate as false. So, in this case, assuming hint
is not filled in properly due to the above mistake, and bind()
is actually failing, you will treat it as success instead, which is why you are seeing "Binding successful"
when you should be seeing "Fail to bind to local port"
.
you are passing the wrong value to the 1st parameter of inet_pton()
. It expects you to pass in the address family of the input string (AF_INET
, etc), but instead you are passing in your m_socket
.
Also, there are some minor issues as well:
m_socket
should be declared as SOCKET
, not as int
.
if bind()
fails, and you were actually treating it as a failure correctly, then you would return EXIT_FAILURE
(ie 1
) instead of returning the actual error code from WSAGetLastError()
, like you do with earlier Winsock failures.
if listen()
fails, you are not returning the Winsock error code.
you are not closing the socket before calling WSACleanup()
.
With that said, try something more like this:
#include <iostream>
#include <string>
#include <windows.h>
int main()
{
std::string m_ipAddress;
int nRet;
// inet_pton() can be called before WSAStartup() ...
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(800);
std::cout << "Enter a local IPv4 address to bind to,\n"
<< "or leave blank to bind to all adapters:" << std::endl;
do {
if (!std::getline(std::cin, m_ipAddress))
return EXIT_FAILURE;
if (m_ipAddress.empty())
{
hint.sin_addr.s_addr = htonl(INADDR_ANY);
break;
}
nRet = inet_pton(AF_INET, m_ipAddress.c_str(), &hint.sin_addr);
if (nRet == 1) break;
if (nRet == SOCKET_ERROR)
{
nRet = WSAGetLastError();
std::cout << "Failed to parse IP address. Error: " << nRet << std::endl;
return nRet;
}
std::cout << "You entered an invalid IP, try again:" << std::endl;
}
while (true);
WSAData wsData;
int nRet = WSAStartup(MAKEWORD(2,2), &wsData);
if (nRet != 0)
{
cout << endl << "Failed to startup Winsock. Error: " << nRet << std::endl;
return nRet;
}
std::cout << "WSAStartup successful" << std::endl;
SOCKET m_socket = socket(AF_INET, SOCK_STREAM, 0);
if (m_socket == INVALID_SOCKET)
{
nRet = WSAGetLastError();
std::cout << "Failed to initialize socket. Error: " << nRet << std::endl;
return nRet;
}
std::cout << "Socket successfully initialized" << std::endl;
nRet = bind(m_socket, (sockaddr*)&hint, sizeof(hint));
if (nRet == SOCKET_ERROR)
{
nRet = WSAGetLastError();
std::cout << "Fail to bind to local port. Error: " << nRet << std::endl;
closesocket(m_socket);
WSACleanup();
return nRet;
}
std::cout << "Binding successful" << std::endl;
nRet = listen(m_socket, SOMAXCONN);
if (nRet == SOCKET_ERROR)
{
nRet = WSAGetLastError();
std::cout << "Fail to listen to local port. Error: " << nRet << std::endl;
closesocket(m_socket);
WSACleanup();
return nRet;
}
std::cout << "Listening Successful" << std:endl;
//...
closesocket(m_socket);
WSACleanup();
return 0;
}