winsock error 10049 trying to bind - c++

I have a problem with server connection. When I try to bind the server to my external device IP I got a winsock error: 10049 Cannot assign requested address. Using localhost server works correctly.
This IP address: 192.168.0.202 ping successfully.
I worked on win8.1. I turned off firewall and windows defender and it did not help.
Code with server implementation has been taken from http://www.planetchili.net/forum/viewtopic.php?f=3&t=3433
#include "Server.h"
Server::Server(int PORT, bool BroadcastPublically) //Port = port to broadcast on. BroadcastPublically = false if server is not open to the public (people outside of your router), true = server is open to everyone (assumes that the port is properly forwarded on router settings)
{
//Winsock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
addr.sin_addr.s_addr = inet_addr("192.168.0.202");
addr.sin_port = htons(1234); //Port
addr.sin_family = AF_INET; //IPv4 Socket
sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket, if we fail to bind the address..
{
std::string ErrorMsg = "Failed to bind the address to our listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
exit(1);
}
if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections, if we fail to listen on listening socket...
{
std::string ErrorMsg = "Failed to listen on listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
exit(1);
}
serverptr = this;
}
bool Server::ListenForNewConnection()
{
SOCKET newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == 0) //If accepting the client connection failed
{
std::cout << "Failed to accept the client's connection." << std::endl;
return false;
}
else //If client connection properly accepted
{
std::cout << "Client Connected! ID:" << TotalConnections << std::endl;
Connections[TotalConnections] = newConnection; //Set socket in array to be the newest connection before creating the thread to handle this client's socket.
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(TotalConnections), NULL, NULL); //Create Thread to handle this client. The index in the socket array for this thread is the value (i).
//std::string MOTD = "MOTD: Welcome! This is the message of the day!.";
//SendString(TotalConnections, MOTD);
TotalConnections += 1; //Incremenent total # of clients that have connected
return true;
}
}
bool Server::ProcessPacket(int ID, Packet _packettype)
{
switch (_packettype)
{
case P_ChatMessage: //Packet Type: chat message
{
std::string Message; //string to store our message we received
if (!GetString(ID, Message)) //Get the chat message and store it in variable: Message
return false; //If we do not properly get the chat message, return false
//Next we need to send the message out to each user
for (int i = 0; i < TotalConnections; i++)
{
if (i == ID) //If connection is the user who sent the message...
continue;//Skip to the next user since there is no purpose in sending the message back to the user who sent it.
if (!SendString(i, Message)) //Send message to connection at index i, if message fails to be sent...
{
std::cout << "Failed to send message from client ID: " << ID << " to client ID: " << i << std::endl;
}
}
//std::cout << "Processed chat message packet from user ID: " << ID << std::endl;
if(Message == "go")
std::cout << "MESSAGE:GO!" << std::endl;
else if(Message == "left")
std::cout << "MESSAGE: GO LEFT!" << std::endl;
else if (Message == "right")
std::cout << "MESSAGE:GO RIGHT!" << std::endl;
else
std::cout << "MESSAGE:DO NOTHING!" << std::endl;
break;
}
default: //If packet type is not accounted for
{
std::cout << "Unrecognized packet: " << _packettype << std::endl; //Display that packet was not found
break;
}
}
return true;
}
void Server::ClientHandlerThread(int ID) //ID = the index in the SOCKET Connections array
{
Packet PacketType;
while (true)
{
if (!serverptr->GetPacketType(ID, PacketType)) //Get packet type
break; //If there is an issue getting the packet type, exit this loop
if (!serverptr->ProcessPacket(ID, PacketType)) //Process packet (packet type)
break; //If there is an issue processing the packet, exit this loop
}
std::cout << "Lost connection to client ID: " << ID << std::endl;
closesocket(serverptr->Connections[ID]);
return;
}
Any ideas?

The bind() function is used to specify which address of the server system is used to accept connections from remote clients, not to specify which remote client is allowed to connect to the server. The bind() function can only be used with addresses that are valid for the server itself, not for addresses of remote devices or hosts.
In order to limit which remote host is allowed to connect to your server, you need to accept the connection and validate the remote address at that time. If the address is not the correct one, the connection is closed.
In general, you want to use INADDR_ANY unless your server is multi-homed (more than one physical connection to more than one network), and only then if you are trying to restrict connections to one of the networks to which your server is attached.

Winsock returns the error flag 10049 (WSAEADDRNOTAVAIL) through its API WSAGetLastError whenever an application tries to bind to an invalid ip Addrress.
binding to a specific IP address means that whenever you run the program (server) the address should be valid (available) but however DHCP gives you dynamic ip addresses everytime you disconnect/connect your adapter so you the address you bound the server the previous time is not valid to correct it open cmd and enter :
ipconfig
you'll get the list of ip4/ip6 addresses then you can pick one of them and bind your server to however this method is really dull so the alternative is to bind to INADDR_ANY so you let the system do the job for you.
you need only from the client to enter the server address and port and connect.

Related

I coded a c++ server/client program using windows sockets. getting 10061 from wsagetlasterror() trying to connect using my public ip addr

Im attempting to connect to my server via my client and if i use my local host address 127.0.0.1 everything works perfectly fine. it connects and im able to send data. however whenever i switch it to my public address it fails to connect. i already went through my router and forwarded the port im using. and ive tested if the port is open with canyouseeme.org and port forward network utilities. the error code i get from getlasterror() is 10061. i also called my isp and they told me the port is open so i should be able to connect but im not. i turned off my firewall and AV as well. i have windows 10 64 bit. im at a loss and would really appreciate the help. the error code means that the server is actively refusing the connection. but nothing happens on my server side...it stays in the accept() call.
this is the server code. how do i solve this issue? i currently have both the server and client on one computer.
class Server
{
public:
Server(int port)
:
port(port)
{
std::cout << "Initializing server...\n";
if (WSAStartup(version, &wsData) == 0)
{
auto result = createListenSock();
//if no value is returned, it was a success
if (!result.has_value())
std::cout << "Successfully created a server! Accepting Clients now.\n";
else
std::cout << result.value() << std::endl;
}
else
std::cout << "Failed to initialize WinSock. Error : " << WSAGetLastError() << std::endl;
}
~Server()
{
closesocket(listensock);
closesocket(client);
WSACleanup();
}
std::optional<std::string> acceptClient()
{
int sz = sizeof(clientinfo);
if ((client = accept(listensock, (sockaddr*)&clientinfo, &sz)) == INVALID_SOCKET)
return {};
else
{
char clientipaddr[100];
inet_ntop(AF_INET, &clientinfo.sin_addr, clientipaddr, sizeof(clientipaddr));
return std::string(clientipaddr);
}
}
private:
std::optional<std::string> createListenSock()
{
//AF_INET for ipv4
//SOCK_STREAM A socket type that provides sequenced, reliable, two-way,
//connection-based byte streams with an OOB data transmission mechanism.
if ((listensock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return "Failed to created listen socket...\n";
initConnectionInfo();
if (bind(listensock, (sockaddr*)&serverInfo, sizeof(serverInfo)) == SOCKET_ERROR)
return "Failed to bind...\n";
if (listen(listensock, SOMAXCONN) == SOCKET_ERROR)
return "Failed to put into listening mode...\n";
//if it returns an empty container, that means it was successful
return {};
}
void initConnectionInfo()
{
//make it use ipv4
serverInfo.sin_family = AF_INET;
//htons converts the port from host to network byte order.
serverInfo.sin_port = htons(port);
//specify that we can accept any ip address
serverInfo.sin_addr.S_un.S_addr = INADDR_ANY;
}
private:
WSADATA wsData;
int version = MAKEWORD(2,2);
SOCKET listensock;
sockaddr_in serverInfo;
int port;
private:
//client variables
SOCKET client;
sockaddr_in clientinfo;
};
int main()
{
//create server
Server server(1024);
auto clientip = server.acceptClient();
if (!clientip.has_value())
{
std::cout << "Couldn't connect to client.";
system("pause");
return 0;
}
std::cout << "Connected to client!" << std::endl << "Client IP Address: " << clientip.value() << std::endl;
and this is the client code
SOCKET startclient()
{
WSADATA data;
//server to connect to
std::string ipAddress = "127.0.0.1"; //IF I CHANGE THIS TO MY PUBLIC IP ADDRESS IT FAILS TO CONNECT
int port = 1024;
// initialize winsock
if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
{
std::cout << "Could not initialize WinSock...\n";
return SOCKET_ERROR;
}
//create a socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
std::cout << "Couldn't create a socket, Error " << WSAGetLastError() << std::endl;
WSACleanup();
return SOCKET_ERROR;
}
//this tells our socket what info to use to connect to the server
sockaddr_in serverinfo;
serverinfo.sin_family = AF_INET;
//htons converts the port number from host to network byte order
serverinfo.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &serverinfo.sin_addr);
std::cout << "Attempting to connect..." << std::endl;
if (connect(sock, (sockaddr*)&serverinfo, sizeof(serverinfo)) == SOCKET_ERROR)
{
std::cout << "Failed to connect... Error : " << WSAGetLastError() << std::endl;
WSACleanup();
closesocket(sock);
return SOCKET_ERROR;
}
else
std::cout << "Connected!" << std::endl;
return sock;
}
int main()
{
SOCKET client = startclient();
if (client == SOCKET_ERROR)
{
system("pause");
return 0;
}

C++ socket error WSAENOTSOCK (10038) after including thread

I created TCP socket connection between client and server.
It is necessary for me to use threads because I'm getting x and y coordinates from another process, and drawing those values with OpenGL.
Only way I had in mind was to create thread for OpenGL drawing, and use main thread to recieve coordinates by socket.
My server side worked perfectly before adding #include <thread>, so I have no idea what could the problem be and why couldn't I use threads while using sockets.
After including thread, after calling recv(), I'm getting error:
WSAENOTSOCK 10038
by using WSAGetLastError();
I think that code is too long for me to post it so I can copy some parts of it that are necessary.
EDIT: code of creating socket and waiting for connection.
// Inicijaliziraj winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wSocket = WSAStartup(ver, &wsData);
if (wSocket != 0) {
cerr << "Problem with initialization of Winsock, exiting!" << endl;
return;
}
// Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "Unable to create a socket! Quitting" << endl;
return;
}
// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; // Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
// Tell winsock socket is for listening
listen(listening, SOMAXCONN);
// Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
/*
if (clientSocket == INVALID_SOCKET) {
cerr << "Unable to connect to client socket, Quitting!" << endl;
return;
}*/
char host[NI_MAXHOST]; // Client's remote name
char service[NI_MAXHOST]; // Service (PORT) the client is connected on
ZeroMemory(host, NI_MAXHOST); // Could use memset(host, 0, )
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " << ntohs(client.sin_port) << endl;
}
// Close listening socket
closesocket(listening);
// While loop: accept and echo message back to client
char buf[4096];
//Opens new thread with canvas because otherwise while loop for recieving will block drawing
//std::thread t1(setDrawing, &iArgc, cppArgv);
while (true) {
ZeroMemory(buf, 4096);
// Wait for client to send data
int bytesRecieved = recv(clientSocket, buf, 4096, 0);
if (bytesRecieved == SOCKET_ERROR) {
int err = WSAGetLastError();
cerr << "Error in recv(). Quitting!" << endl;
break;
}
if (bytesRecieved == 0) {
cout << "Client disconnected " << endl;
break;
}
My server side worked perfectly before adding #include <thread>, so I have no idea what could the problem be and why couldn't I use threads while using sockets.
One thing to pay attention to is that <thread> is a C++ STL header. If your code happens to have a using namespace std; statement, your socket code may end up calling the STL's std::bind() function instead of WinSock's bind() function, which would in turn cause listen() to fail with an WSAEINVAL error. Which you are not checking for since you are not doing any error handling on your bind() or listen() calls. So be aware of that. Avoid using namespace std; statements, or call WinSock's bind() as ::bind() instead. And ALWAYS do error handling on API calls.
You have also commented out your error handling on accept(). If bind() and listen() fail, so will accept(), causing it to return INVALID_SOCKET. Which could explain why you are then getting the WSAENOTSOCK error on recv().

TCP Server Socket Opening Fail in C++

I am currently creating a program where I require a TCP server for communication with an android application. I have written and tested the TCP server as an individual project and it runs completely fine. When including this into a larger project, where I have other processes, it no longer opens the socket for listening.
My project is being created in Visual Studio 2017 and the libraries I am using are:
WS2_32.lib for the TCP
OpenCV for image processing
Libcurl for sending files to a database
ACTi SDK for pulling image feed from a camera
The TCP server code I have written is (taken from https://www.youtube.com/watch?v=WDn-htpBlnU&t=162s):
void TCPServer()
{
//Initalize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't init winsock" << endl;
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create socket" << endl;
return;
}
//Bind the socket to an ip address and port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(100);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could use inet_pton()
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell Winsock the socket is for listening
listen(listening, SOMAXCONN);
//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientsocket = accept(listening, (sockaddr*)&client, &clientSize);
char host[NI_MAXHOST]; //Clients remote name
char service[NI_MAXHOST]; //Service the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << "connected on port " << service << endl;
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " << ntohs(client.sin_port) << endl;
}
//Close listening socket
closesocket(listening);
//While loop:accept and echo message back to client
char buf[4096];
while (true)
{
ZeroMemory(buf, 4096);
//Wait for client to send data
int bytesReceived = recv(clientsocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR)
{
cerr << "Error in recv()" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client disconnected" << endl;
break;
}
cout << buf << endl;
}
//Close the socket
closesocket(clientsocket);
//cleanup windsock
WSACleanup();
}
As I said, this code works as an individual project however, when I include this into my overall project the socket fails to open and a connection to 204.204.204.204 is instantly made. This was checked in both situations by viewing all open sockets with netstat. I feel this may be a library conflict, maybe between WS2_32 and libcurl, however I am unsure.
I am currently testing this by calling TCPServer() in my main, however I plan to run the server threaded along with my other processes.
Any suggestions as to why the socket may be failing to open would be much appreciated.
After carrying out checks on the function it was possible to narrow the failure down to the bind(...) function. It seems the error is down to having using namespace std;
The solution was to call bind from the global namespace by doing ::bind(...). This solution was found here: Compilation errors with socket bind function

not getting a Winsock error when ethernet unplugged

I'm working on a client application that sends sensor data one way to a remote server. After the initial login there is no return data from the server. My problem is when the ethernet is disconnected such as a hard disconnect i.e. wireless link goes down, my application does not get a error return value after attempting a 'send' call. I am using a single non-blocking socket instance. The thread checks for a 'recv' each loop using 'select'. It does eventually get an error on 'recv' but never on 'send'.
When the remote PC has a internet connectivity loss it will cause the program to be disconnected from the server for minutes to hours before it recognises the connection loss happened and switches to re-login the server. What can be done to help detect the hard disconnect?
void checkConnect(NTRIP& server)
{
//1st check for recv or gracefully closed socket
char databuf[SERIAL_BUFFERSIZE];
fd_set Reader, Writer, Err;
TIMEVAL Timeout;
Timeout.tv_sec = 1; // timeout after 1 seconds
Timeout.tv_usec = 0;
FD_ZERO(&Reader);
FD_ZERO(&Err);
FD_SET(server.socket, &Reader);
FD_SET(server.socket, &Err);
int iResult = select(0, &Reader, NULL, &Err, &Timeout);
if(iResult > 0)
{
if(FD_ISSET(server.socket, &Reader) )
{
int recvBytes = recv(server.socket, databuf, sizeof(databuf), 0);
if(recvBytes == SOCKET_ERROR)
{
cout << "socket error on receive call from server " << WSAGetLastError() << endl;
closesocket(server.socket);
server.connected_IP = false;
}
else if(recvBytes == 0)
{
cout << "server closed the connection gracefully" << endl;
closesocket(server.socket);
server.connected_IP = false;
}
else //>0 bytes were received so read data if needed
{
}
}
if(FD_ISSET(server.socket, &Err))
{
cout << "select returned socket in error state" << endl;
closesocket(server.socket);
server.connected_IP = false;
}
}
else if(iResult == SOCKET_ERROR)
{
cout << "ip thread select socket error " << WSAGetLastError() << endl;
closesocket(server.socket);
server.connected_IP = false;
}
//2nd check hard disconnect if no other data has been sent recently
if(server.connected_IP == true && getTimePrecise() - server.lastDataSendTime > 5.0)
{
char buf1[] = "hello";
cout << "checking send for error" << endl;
iResult = send(server_main.socket, buf1, sizeof(buf1), 0);
if(iResult == SOCKET_ERROR)
{
int lasterror = WSAGetLastError();
if(lasterror == WSAEWOULDBLOCK)
{
cout << "server send WSAEWOULDBLOCK" << endl;
}
if(lasterror != WSAEWOULDBLOCK)
{
cout << "server testing connection send function error " << lasterror << endl;
closesocket(server.socket);
server.connected_IP = false;
}
}
else
{
cout << "sent out " << iResult << " bytes" << endl;
}
server.lastDataSendTime = getTimePrecise();
}
}
It is not possible to detect disconnect until you try to send something.
The solution for you is the following:
You detect that you have received no data for a certain period of time and you want to check is the connection is alive.
You send some data to the server using send function. It could be protocol-specific ping packet or either garbage. The send function returns immediately, because it does not wait for actual data send. It only fills internal send buffer.
You begin waiting for socket read.
While you are waiting, OS tries to send the data in the send buffer to the server.
When OS detects that it cannot deliver data to the server, then the connection is marked as erroneous.
Now you will get an error when calling recv and send functions.
The send timeout is system specific and can be configured. Usually, it is about 20 seconds (Linux) - 2 minutes (Windows). It means that you need to wait a lot before you receive an error.
Notes:
You can also turn on TCP keep alive mechanism, but I don't recommend you to do this.
You can also modify TCP timeout intervals. It can be helpful when you want the connection to survive the temporary network disconnect.
That's how TCP works and is intended to work. You will get an error from a subsequent send, but never from the first send after the disconnect. There is buffering, and retry, and retry timeout to overcome before an error is signalled.

Winsock connect() hanging on one network, but not another

I am having trouble using the connect() function. My code was completely working before, but now I have moved to a different physical network and my blocking call to connect() no longer works, and just seems to hang indefinitely. Receiving broadcasts over UDP still works fine. Going back to the old network it works fine again. I cant for the life of me figure out why it works on one network and not the other. I have checked firewall settings and they are correct. What could be going on?
I have a pre-defined port being used and I am getting the address from the broadcast. I use recievefrom to receive the broadcast and set the outgoing ip address from it
ret = recvfrom (bcast, bcast_read,sizeof(j4cDAC_broadcast),0,(sockaddr*)&from,&size);
to.sin_addr = from.sin_addr;
local.sin_addr.s_addr = inet_addr("0.0.0.0");
Then for the TCP connection I have
dac = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// cout << "SOCKET\n";
if (dac == INVALID_SOCKET)
{
SetConsoleTextAttribute(console,(WORD)12);
cout << "TCP socket failed: " << WSAGetLastError();
connected_ = false;
return(1);
}
//set SO_REUSEADDR on a socket to true (1):
bool optval = true;
setsockopt(dac, SOL_SOCKET,SO_DONTLINGER,(const char*)&optval, sizeof(optval));
int pies = setsockopt(dac, SOL_SOCKET,SO_REUSEADDR,(const char*)&optval, sizeof(optval) );
if (pies == SOCKET_ERROR )
{
SetConsoleTextAttribute(console,(WORD)12);
cout << "SETSOCKOPT ERROR: " << WSAGetLastError() << endl;
} // */
local_T = local;
local_T.sin_port = htons ((short)TCPport);
//bind the tcp socket
bndt = bind(dac,(SOCKADDR*) &local_T,sizeof(local_T) );
if (bndt == SOCKET_ERROR )
{
SetConsoleTextAttribute(console,(WORD)12);
cout << "BIND TCP FAILED: " << WSAGetLastError();
if (WSAGetLastError() == WSAEACCES)
cout << "ACCESS DENIED";
cout << endl;
SetConsoleTextAttribute(console,(WORD)7);
shutdown(dac,2);
closesocket(dac);
connected_ = false;
return 1;
}
c = connect(dac, (sockaddr*) &to, size); // <------- This hangs
if (c == SOCKET_ERROR)
{
cout << "connection problem: " << WSAGetLastError() <<endl;
}
connected_ = true;`
I found this to be an issue with VMWare virtual networking devices. Even though I had no virtual machines running, after much testing of various things, I found the device broadcast was being received on one of the virtual networking interfaces from VMWare somehow. Disabling these two devices has fixed this issue.