WinSock2: connect() delivers 'connection refused' - c++

I have been trying to get a simple SFTP program working with code from this website, but I have not been able to get it to even send out data without it returning error code 10061 (WSAECONNREFUSED). I have tried using Wireshark on the active interface with all firewalls disabled, but it didn't say anything was being sent to the address I gave (ex: 72.196.212.127). However, when I give it a local address like 192.168.1.101, it gives error code 10060 (WSAETIMEDOUT), still not sending out any data on the network. I am able to connect to the target machine on both address with software like Putty and WinSCP and ping it on the command prompt.
Here is the relevant part of my connection method:
// Open socket
WSADATA data;
int err = WSAStartup(MAKEWORD(2, 0), &data);
if (err != 0) return "ERROR: Failed to initialize WSA";
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = to_uint32_t(ip);
if (net::connect(sock, (struct sockaddr*) &sin, sizeof(struct sockaddr_in)) != 0) return "ERROR: Could not connect to host. Code: " + std::to_string(WSAGetLastError());
The variable port is an integer (value = 22), with ip being a string (192.168.1.101 or 72.196.212.127). This function returns the "Could not connect to host" error. No other errors occur.
Here is the to_uint32_t method:
std::uint32_t to_uint32_t(const std::string& ip_address)
{
const unsigned bits_per_term = 8;
const unsigned num_terms = 4;
std::istringstream ip(ip_address);
uint32_t packed = 0;
for (unsigned i = 0; i < num_terms; ++i)
{
unsigned term;
ip >> term;
ip.ignore();
packed += term << (bits_per_term * (num_terms - i - 1));
}
return packed;
}

#selbie pointed out that I was not using the correct function for resolving the IP. To fix my code, I just switched sin.sin_addr.s_addr = to_uint32_t(ip); to inet_pton(AF_INET, ip, &sin.sin_addr);.

Related

Getting an error wile trying to open a TCP socket - c++

I'm trying to build a block that acts as server and client to send and receive data (2 duplicate versions in 2 different computers) through a TCP connection.
This is what I did and I'm trying to test using the windows commandd line "netstat -ab" to try to find the tcp connection but I can't find it.
Apart from the given error, what am i doing wrong?
bool IPTunnel::runBlock(void) {
int ready =
inputSignals[0]->ready(); // int ready2 = inputTCPConnetion[0]->ready();
// server
SOCKET sockfd, newsockfd;
int portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
SOCKET n;
// create a socket(int domain, int type, int protocol)
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) printf("\n ERROR opening socket");
// bzero((char *)&serv_addr, sizeof(serv_addr));
portno = 5500;
serv_addr.sin_family = AF_INET;
char ipad[10] = "127.0.0.1";
serv_addr.sin_addr.s_addr = *ipad; // INADDR_ANY;
serv_addr.sin_port = htons(portno);
// if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
auto sd = bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
// if (sd < 0)
// printf("\n ERROR on binding");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if(newsockfd < 0) printf("ERROR on accept");
printf("server: got connection from %s port %d\n",
inet_ntop(serv_addr.sin_family, &ipad, buffer, clilen),
ntohs(cli_addr.sin_port));
send(newsockfd, "Hello, world!\n", 13, 0);
// bzero(buffer, 256);
n = _read(newsockfd, buffer, 255);
if(n < 0) printf("ERROR reading from socket");
printf("Here is the message: %s\n", buffer);
while(true) {
}
// close(newsockfd);
// close(sockfd);
return 0;
}
This is the error that gives: Unhandled exception at 0x00007FFE5031B7EC (ucrtbased.dll) in ip_tunnel.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
in the _read function...
Well, this line is definitely wrong:
serv_addr.sin_addr.s_addr = *ipad; //INADDR_ANY;
If you want to receive incoming TCP connections on the loopback device, you should do something more like this:
serv_addr.sin_addr.s_addr = inet_aton("127.0.0.1");
(or if you want them to be received from any connected network device, specify INADDR_ANY instead)
Also, make sure you called WSAStartup() at the beginning of your program, Windows sockets won't work correctly if you haven't done that.
One last nitpick:
while(true){}
is not a good way to pause execution of your program. For one thing, it will typically spin a CPU at 100% usage, which is very inefficient, and for another, it invokes undefined behavior according to the C++ standard.
A better way to do get that behavior would be something like:
while(true) {Sleep(1000);}
Also this part is wrong/weird:
SOCKET n;
[...]
n = _read(newsockfd, buffer, 255);
... in that _read doesn't return a SOCKET, it returns an int. I think you meant to declare int n; instead.
One last potential problem: if your call to bzero(buffer, 256); is commented out, then it's quite possible for buffer to contain no zero-bytes after the _read() call returns, in which case your printf("Here is the message: %s\n", buffer); call afterwards could read right past the end of the buffer array and out into the wild blue yonder of other memory, potentially causing a crash (or at least causing a lot of garbage bytes to be printed). The fix is to make sure the buffer array contains a 0/NUL byte at the end of the valid bytes that were placed there by the _read() call.

Directed UDP to IP address that doesn't exist

I am experiencing slowdowns when attempting to send a UDP message to an IP address that is non-existent. We read a list of IP/ports out of a configuration file and expect that those combinations will exist. In some situations, the remote machine may not be online yet and the IP will not exist on the network. In this case, i would prefer that we do not attempt to send the data.
I'm looking for suggestions on a good way to determine that the IP doesn't exist in order to skip sending the data. I do not want to completely remove it from the list because there is the chance that the machine may come online and i'd like to continue sending data.
Relevant code:
int SendData(const char *data, int size, bool openIfClosed)
{
std::lock_guard<std::mutex> lock(sendMutex);
//if the socket was not already opened, close it after i do my send
bool closeAfterSend = mySocket == INVALID_SOCKET ? true : false;
if (!OpenSocket(openIfClosed))
return 0;
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(remotePort);
address.sin_addr.s_addr = remoteIPAddress.GetIPAddressAsULong();
//check if remote address exists prior to send?
int bytesSent = sendto(mySocket, data,
size, 0, (struct sockaddr *)&address, sizeof(address));
if (bytesSent == size)
numMsgsOut++;
else
{
//fail
}
if (closeAfterSend && openIfClosed)
{
closesocket(mySocket);
mySocket = INVALID_SOCKET;
}
return bytesSent;
}

udp server sending data to specific client until any recvfrom

I writing a library that should implement UDP-based protocol.
I'm host A, remote is host B.
I need to send message from host A, port 7011, to host B port 7011. Then Host B will answer to the host A, port 7011. Communication is async, so I need the udp which will listen for incoming messages, and also sometimes I need to send messages from the same port the server is binded to.
Here is how i'm creating and binding socket:
udp_server::udp_server(const std::string &localAddress, int localPort)
: f_port(localPort), f_addr(localAddress) {
char decimal_port[16];
snprintf(decimal_port, sizeof(decimal_port), "%d", f_port);
decimal_port[sizeof(decimal_port) / sizeof(decimal_port[0]) - 1] = '\0';
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
int r(getaddrinfo(localAddress.c_str(), decimal_port, &hints, &f_addrinfo));
if (r != 0 || f_addrinfo == NULL) {
throw udp_client_server_runtime_error(
("invalid address or port for UDP socket: \"" + localAddress + ":" + decimal_port + "\"").c_str());
}
f_socket = socket(f_addrinfo->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
if (f_socket == -1) {
freeaddrinfo(f_addrinfo);
throw udp_client_server_runtime_error(
("could not create UDP socket for: \"" + localAddress + ":" + decimal_port + "\"").c_str());
}
r = bind(f_socket, f_addrinfo->ai_addr, f_addrinfo->ai_addrlen);
if (r != 0) {
freeaddrinfo(f_addrinfo);
close(f_socket);
throw udp_client_server_runtime_error(
("could not bind UDP socket with: \"" + localAddress + ":" + decimal_port + "\"").c_str());
}
}
And here I'm trying to send message:
ssize_t udp_server::sendto(std::string remoteHost, uint16_t port, const char *message, size_t messageLength) {
struct sockaddr_in remote;
remote.sin_family = AF_INET;
remote.sin_port = htons(7011);
remote.sin_addr.s_addr = ::inet_addr("10.8.0.6");
socklen_t addrSize;
addrSize = sizeof(remote);
memset(remote.sin_zero, '\0', sizeof(remote.sin_zero));
dout << "messageLength: " << messageLength << std::endl;
return ::sendto(this->f_socket, message, messageLength, 0, (struct sockaddr *)&remote, addrSize);
}
But ::sendto always returns -1. And errno is set to 22, which means invalid argument. What is the possible solutions? Maybe overall structure is bad.
=== Solution ===
I've bind my server to locahost :(
Should be 0.0.0.0 or INADDR_ANY.
This error can occur if you bind to localhost and attempt to send to a non-local IP.
If you want to be able to send from any interface, you should bind to 0.0.0.0.
Also, in udp_server::sendto, you set remote.sin_port and remote.sin_addr to hardcoded values. You probably want to use the remoteHost and port parameters here.

Socket programming in Linux by C++

I am developing a C++ app in openSUSE 12.3 and one of it's part is responsible to send data to a device via Socket (in LAN). I am using this code
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *printer;
portno = 9100;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) error("ERROR opening socket\n");
printer = gethostbyname("100.0.69.23");
if(printer == NULL) error("No such device on 100.0.69.23\n");
//set bit set to zero
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) printer->h_addr, (char *) &serv_addr.sin_addr.s_addr, printer- >h_length);
serv_addr.sin_port = htons(portno);
if(connect(sockfd, (struct sockaddr *) & serv_addr, sizeof(serv_addr)) < 0)
{error("ERROR connecting");
return;
}
n = write(sockfd, data, datalenght);
if(n < 0) error("ERROR sending command to printer");
n = read(sockfd, buffer, 200);
I think the code is correct but the connect function returns -1 and seems that could not connect to the device (printer) . This code was written in openSUSE 11 and was working OK and I could send/receive data to device but when I copy/paste it to new system (openSUSE 12.3) it gives me failure in connecting. I ping result on the specific IP which is in use show that device is reachable via LAN
I think you should consider the possibility that hostent returned by gethostbyname function might have AF_INET6 address family (in which case it will be IPv6 instead of IPv4 address).
http://linux.die.net/man/3/gethostbyname
So you can either use GNU extension function gethostbyname2 function that will allow you to specify address family.
printer = gethostbyname2("100.0.69.23", AF_INET);
Or instead you can use getaddrinfo function, as gethostbyname function is said to be obsolete, by the documentation.
As already mentioned, you are checking for printer == NULL before initializing it. I think you meant the following instead:
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket\n");
printer = gethostbyname("100.0.69.23");
...
Also the structure of the code seems to indicate that when you want to send a command to the printer you connect(), write() then read(), which is OK if you are only ever sending one command, but suboptimal if you are sending multiple commands. In the latter case you want to separate the connect() from the write() as it's fairly expensive to connect so you want to do it just once.

Reopen connected datagram socket

I have a connection protocol that has been defined by our customer. Data are sent between two linux computers using UDP and TCP protocols. The IP addresses and ports are fixed on startup.
We are sending messages at 200 Hz and I have been using connect to save some time on the transmissions.
My problem is that if there is a communication error, I need to tear down the connections and reinitialise.
I have a problem with one of the UDP connections as it will not rebind to the required address and returns errno 22.
The code I am using is something like:
int
doConnect(int& sock, int local_port, char *local_ip, int remote_port, char *remote_ip)
{
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(local_port);
inet_pton(local_ip,&addr.sin_addr.s_addr);
if (0 > bind(sock, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("Bind Error errno = %d\n", errno);
return ERR_BIND;
}
memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(remote_port);
inet_pton(remote_ip,&addr.sin_addr.s_addr);
if (0 > connect(sock, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("Connect Error errno = %d\n", errno);
return ERR_CONNECT;
}
return ERR_OK;
}
The way that this is used is like this:
int s1(-1), s2(-1);
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");
When an error occurs
close(s1);
close(s2);
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");
Here the local address is 172.17.21.3 and I am connecting to 172.17.21.1. s1 listens to a broadcast message.
s1 successfully reconnects to the remote machine, but s2 fails with error 22 from the call to bind.
I have tried explicitly calling bind and connect to an AF_UNSPEC address immediately before I close the socket. This doesn't solve the problem.
Are there any options that I should be using?
Perhaps you could try:
int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
I also suggest you double check that you're not passing the same socket to the two consecutive doConnect() calls (as errno 22 = EINVAL, which in the case of bind() appears to mean that the socket is already bound to an address).
The underlying socket layer might hold the port & IP address still open, even after your call to close. Try some of the following:
do a sleep(10) (or more) between the close and the call to doConnect again
configure the sockets using setsockopt with the SO_LINGER set to off
This actually happens more commonly with TCP connections, but I see no reason UDP can't have this problem as well.