connecting to an IP address instead of localhost? - c++

this is my second go at this, I've written a server application as below which outputs whatever the client sends. I have one server.exe version where it listens to anything using INADDR_ANY, Having done that I can use my client and connect to the server if I specify the client connect to localhost (Which all works fine).
but if I use my own IP address instead of localhost for the client, I cannot connect to the server?. Shouldn't I be able to connect to the server this way?.
I used another server.exe which was hard-coded to use my IP address without having INADDR_ANY but it wasn't able to bind() or listen() to incoming connections. I'm confused as to how to proceed.
(I'm running the server and client on the same machine, is that an issue?)
server
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
using namespace std;
#define PORT 3490
#define IP "118.93.0.164"
#define BACKLOG 10
const int winsockversion = 2;
int main(void){
WSADATA wsadata;
if ( (WSAStartup(MAKEWORD(winsockversion,0),&wsadata)) == 0){
cout<<"-WSAStartup Initialized." << endl;
struct sockaddr_in serv;
memset(&serv,0,sizeof serv);
serv.sin_family = AF_INET;
serv.sin_port = htons(PORT);
serv.sin_addr.s_addr = inet_addr(IP);//INADDR_ANY;//inet_addr(IP);
//---------------------------------------
struct addrinfo serv_addrinfo;
serv_addrinfo.ai_family = AF_INET;
serv_addrinfo.ai_socktype = SOCK_STREAM;
serv_addrinfo.ai_protocol = IPPROTO_TCP;
serv_addrinfo.ai_addrlen = sizeof(serv);
serv_addrinfo.ai_addr = (sockaddr*)&serv;
//---------------------------------------
SOCKET serv_con;
serv_con = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (serv_con != INVALID_SOCKET){
cout<<"-Server Socket created." << endl;
}
if (bind(serv_con,serv_addrinfo.ai_addr,serv_addrinfo.ai_addrlen) != -1){
cout<<"-Binding Successful." << endl;
}
if( listen(serv_con,BACKLOG) != -1){
cout<<"-Listening for incoming connections." << endl;
}
//--------------------------------------------------------------------
SOCKET recv_socket;
struct sockaddr_in client_info;
int client_info_size = sizeof(client_info);
char *con_addr = inet_ntoa(client_info.sin_addr);
recv_socket = accept(serv_con,(sockaddr*)&client_info,&client_info_size);
if( recv_socket != INVALID_SOCKET ){
cout<<"-Connection Established!. " << endl;
cout<<"-Connected to: [" << con_addr << "] " << endl;
//----------------------------------------------------------------------
char buffer[80];
int bytes_in;
while(true){
bytes_in = recv(recv_socket,buffer,sizeof(buffer),0);
if ( bytes_in > 0 ){
cout<<"[" << con_addr << "]" << buffer << endl;
}
if (bytes_in == 0 ){
cout<<"[" << con_addr << "] has disconnected." << endl;
break;
}
if (bytes_in == -1 ){
cout<<"-Possible Abrupt disconnecton from [" << con_addr << "]" << endl;
break;
}
}
closesocket(recv_socket);
closesocket(serv_con);
}
}else{
cout<<"-WSAStartup Initialization failed." << endl;
}
if( WSACleanup()!= -1){
cout<<"-WSACleanp Successful." << endl;
}
WSAGetLastError();
return 0;
}
client
/*client*/
#define _WIN32_WINNT 0x501
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
using namespace std;
#define PORT "3490"
#define SERVER "118.93.0.164" // and localhost
const int winsockVersion = 2;
int main(void){
WSADATA wsadata;
if ( (WSAStartup(MAKEWORD(2,0),&wsadata)) == 0){
cout<<"-WSAStartup Initialized." << endl;
struct addrinfo hints, *res;
int sockfd;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(SERVER,PORT,&hints,&res) != 0){
cout<<"-getaddrinfo unsuccessful." << endl;
}
if ( (sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol)) == -1 ){
cout<<"-Unable to create socket." << endl;
}
if ( (connect(sockfd,res->ai_addr,res->ai_addrlen)) != -1 ){
cout<<"-Connection Established." << endl;
}
cout<<"-Client connecting to: " << res->ai_addr << endl;
while(true){
string text_buff;
cout<<"Enter text: ";
getline(cin,text_buff);
if( (send(sockfd,text_buff.c_str(),text_buff.length()+1,0)) != -1 ){
cout<<"-text_buff sent!." << endl;
}
}
}else{
cout<<"-WSAStartup Initialization failed." << endl;
if(WSACleanup()!=0){
cout<<"-WSACleanup Successful." << endl;
}else{
cout<<"-WSACleanup Failed." << endl;
}
}
return 0;
}

If you have a router you will have to set up Port forwarding. It really depends on what kind of router you have, so you will have to look it up for your specific one.
You cannot bind to your ISP's IP address, since you do not own it (the router does). You have to bind to an IP address that your computer actually owns, which is found via ipconfig /all in windows. Then make sure to forward traffic in your router for your servers portnumber, to the internal ipaddress that your computer has.

When you're trying to connect back to the server, are you using localhost/127.0.0.1, or the IP address you're listening on?
It may be that trying to connect to 'localhost' attempts to use the loopback interface, which your program isn't listening on. I'm not 100% sure how it works in Windows.
Can I ask a more important question that may prompt you to change your design: why do you want to bind to a particular IP (and localhost)?

you may try using cmd to ping to server IP from your client side to see whether it is a connection problem.
Furthermore, i think this
#define PORT "3490"
in client side is wrong since port should be an integer.

Related

Website not responding when sending a GET request using low level c++ networking libraries

I am trying to create a program that downloads data from websites using c++ low level networking.
Here is the code:
#include <iostream>
#include <string>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int status, sock;
struct addrinfo hints;
struct addrinfo *servinfo;
int main(int argc, char** argv){
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int MAXDATASIZE = 100;
char request[] = "GET /robots.txt HTTP/1.1\n";
char buf[MAXDATASIZE];
if((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0){
std::cout << "getaddrinfo: " << gai_strerror(status) << "\n";
return 2;
}
if((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1){
std::cout << "Error creating socket\n";
return 2;
}
if(connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1){
std::cout << "Error connecting to host " << argv[1] << " at port " << argv[2] << "\n";
return 2;
}
if((send(sock, request,strlen(request), 0)) == -1){
std::cout << "Error communicating with website\n";
return 2;
}
if(recv(sock, buf, MAXDATASIZE, 0) == -1){
std::cout << "Error recciving data from " << argv[1] << " at port " << argv[2] << "\n";
}
std::cout << buf << std::endl;
close(sock);
freeaddrinfo(servinfo);
}
When I try to connect to google, using www.google.com as the host and 80 as the port, it hangs at the recv() call.To test whether the request was the problem, I connected to google using telnet with the same request, and it worked. I also tried binding netcat to a port on my computer, and then connected to that port using my program. The request was sent properly to netcat, and when I responded with a test message, my program reccived it.
Does anyone know why google isn't sending the data?
I'm using fedora 32, if that might help
Your software is not hanging. Rather, the server is waiting for an indication that the client has finished sending the headers, which is indicated by sending an empty line. Until the client sends the blank line, the server cannot respond.
Change your request to:
char request[] = "GET /robots.txt HTTP/1.1\r\n\r\n";

WinSock c++ inet_ntop always displays 204.204.204.204 (and accept() didn't failed)

I'm trying to make a winsock server and I want to display the client's ip on the server when he connects but that's where there is a problem. Every time I try to connect it display 204.204.204.204. I tried to connect with another computer but the result was the same.
result in localhost
After this, I started looking for people having the same problem as me on this website and I found several people who had the same as me but they all had either the accept or the inet_ntop function that wasn't working correctly. So I check and none of this two functions return an error. Maybe I'm stupid but I really can't figured out what's the problem. (btw english is not my first language so please tell me if you noticed or if my english isn't too bad)
the part of the code that isn't working
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
the whole code if you need it
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string>
#pragma comment(lib, "ws2_32.lib")
int main()
{
std::cout << "--- Tcp/ip Server ---" << std::endl;
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
if (server == INVALID_SOCKET)
{
std::cout << "error in SOCKET(): "<< WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in s;
s.sin_family = AF_INET;
s.sin_addr.s_addr = INADDR_ANY;
s.sin_port = htons(52000);
// bind
if (bind(server, (sockaddr*)&s, sizeof(s)) == SOCKET_ERROR)
{
std::cout << "Error: bind()" << std::endl;
}
//listen
if (listen(server, SOMAXCONN) == SOCKET_ERROR)
{
std::cout << "Error in listen(): " << WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
// the code isn't finished yet
system("pause");
WSACleanup();
}
return 0;
}
You are passing the address of the wrong variable in the second parameter of accept().
You are passing the address of your SOCKET client variable that you are about to assign the result of accept() to. C++ allows a variable's address to be taken when declaring and initializing the variable in the same statement. But that is not what you want in this case. You need to pass the address of your sockaddr_in from variable instead:
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&from, &clientlen); // <-- &from instead of &client
You are leaving your from variable uninitialized, and your compiler fills uninitialized variables with 0xCC (decimal 204) bytes in debug mode, so that is why you end up seeing 204.204.204.204 (hex 0xCC 0xCC 0xCC 0xCC) from inet_ntop() when you don't initialize your from variable properly.

C++ Socket Connection on Linux

I'm new to C++ and am trying to setup a connection to a remote server but having problems getting it to work. Spec: Ubuntu 16.04, pre-installed g++ compiler and when I run the following code it returns "pre-standard C++":
if( __cplusplus == 201103L ) std::cout << "C++11\n" ;
else if( __cplusplus == 19971L ) std::cout << "C++98\n" ;
else std::cout << "pre-standard C++\n" ;
My code is as follows:
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
using namespace std;
int main() {
int client;
int portNum = 80;
bool isExit = false;
int bufsize = 1024;
char buffer[bufsize];
const char ip[] = "216.58.210.36"; //google ip for test connection
const char req[] = "GET / HTTP/1.1\nHost: www.google.com"; //test
char res[bufsize];
struct sockaddr_in server_addr;
client = socket(AF_INET, SOCK_STREAM, 0);
if (client < 0) {
cout << "\nError establishing socket..." << endl;
exit(1);
}
cout << "\n=> Socket client has been created..." << endl;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portNum);
inet_aton(ip, &server_addr.sin_addr);
if (connect(client,(struct sockaddr *)&server_addr, sizeof(server_addr)) == 0){
cout << "=> Connection to the server port number: " << portNum << endl;
}
send(client, req, bufsize, 0);
cout << "=> Awaiting confirmation from the server..." << endl;
recv(client, buffer, bufsize, 0);
cout << "=> Connection confirmed, response:" << buffer << endl;
cout << res << endl;
close(client);
return 0;
}
The client is created and the socket connects but the code hangs on the call to recv() and no response is received. I'm assuming that's because the request I'm sending is in the wrong format/data type/etc. Can anyone advise where I'm going wrong? Cheers!
You haven't sent a complete HTTP request so the server is waiting for more data.
You need to use \r\n as your line separator and your request has to end in a blank line:
const char req[] = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
Plus as others have commented you need to check for errors.
You are also sending 1024 bytes of data from a buffer which is much smaller.

UDP over NAT fail

I have this code:
#include <cstring>
#include <cstdio>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <stdlib.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <thread>
#include "STUN.h"
bool do_work = true;
using namespace std;
void receiver(int sock) {
//boost::asio::io_service& s
sockaddr_in from_adr;
std::cout << "START: receiver\n";
size_t blen = 2048;
char * buf = new char[blen];
unsigned slen = sizeof(from_adr);
if (recvfrom(sock, (void *) buf, blen, 0, (sockaddr*) &from_adr, &slen)
< 0) {
std::cout << "Recv problem\n";
exit(0);
}
do_work = false;
std::cout << "STOP: receiver\n";
}
void sender(sockaddr_in * to, int sock) {
std::cout << "START: sender\n";
while (do_work) {
if (sendto(sock, "OK", 3, 0, (sockaddr*) to, sizeof(sockaddr)) < 0) {
std::cout << "SEND PROBLEM\n";
return;
}
sleep(1);
}
std::cout << "RECEIVED!!!\n\n\n";
exit(0);
}
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: udp-flood-test <port>\n";
return 1;
}
ippd stun_adr;
stun_adr.addr = "64.233.161.127";
stun_adr.port = 19302;
STUN stun(stun_adr);
std::string eip;
uint16_t epp;
uint16_t lp = std::atoi(argv[1]);
ippd sti = stun.getSTUN(lp);
std::cout << "External address: " << sti.addr << ":" << sti.port << "\n";
std::cout << "Internal address: " << "127.0.0.1:" << lp << "\n";
std::cout << "Write external ip: ";
std::cin >> eip;
std::cout << "\n";
std::cout << "Write external port: ";
std::cin >> epp;
std::cout << "\n";
std::cout << "OK. I'll send data to " << eip << ":" << epp << "\n";
int m_sock; // дескриптор сокета
sockaddr_in m_addr; // переменная адреса интерфейса
std::string my_addr = "0.0.0.0"; // Адрес локального интерфейса
/* Создание сокета и присвоение значения дескриптору сокета для UDP пакетов
* PF_INET - IP protocol family
* SOCK_DGRAM - Raw protocol interface */
if ((m_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return -1;
}
/* Обнуляем переменную m_addr и забиваем её нужными значениями */
memset(&m_addr, 0, sizeof(m_addr));
m_addr.sin_family = AF_INET; // обязательно AF_INET!
m_addr.sin_port = htons(lp); // 0 - выдать порт автоматом
/* Переводим адрес в нужный нам формат */
if (inet_aton(my_addr.c_str(), &m_addr.sin_addr) == 0) {
perror("inet_aton");
close(m_sock);
return -1;
}
/* Биндим сокет */
if (bind(m_sock, (struct sockaddr*) &m_addr, sizeof(m_addr)) < 0) {
perror("bind");
close(m_sock);
return -1;
}
sockaddr_in to_addr;
memset(&to_addr, 0, sizeof(to_addr));
to_addr.sin_family = AF_INET;
to_addr.sin_port = htons(epp);
if (inet_aton(eip.c_str(), &to_addr.sin_addr) == 0) {
perror("inet_aton");
close(m_sock);
return -1;
}
std::thread inp(receiver, m_sock);
std::thread oup(sender, &to_addr, m_sock);
oup.detach();
inp.detach();
while (1) {
sleep(1);
}
return 0;
}
It's a simple test program to get external ip and port over STUN and send data from peer A to peer B (and from B to A).
So program works fine if I set IPs and ports as 127.0.0.1:port or local_network_ip:port.
If I set IP received from STUN server peer A will send UDP packets to peer B. And B will send packets to A. But A and B haven't any incoming packets. In Wireshark I can see outgoing packets too, but no incoming.
Network connection diagram:
A (pc with active test program) - NAT (home router) - ... - NAT (internet provider) - internet - NAT (another internet provider) - ... - NAT (another home router) - B (another pc with active test program)
Maybe I'm doing something wrong?..
Where can I find a problem?
Problem is in double NAT. Home routers (from network diagram) rejecting packets if you have no configured port forwarding.
Follow this steps to work over double NAT:
select local port to receive packets.
try to bind port. (if failed then return to step 1)
configure port forwarding in home router using NAT-PMP or UPnP IGD.
use STUN to get your external IP and port
share data from step 4 to another program instance
send and/or receive UDP packets

Why this WinSock code is not connecting to client?

I am new to Winsock programming and came across this code while reading the book "Network Programming For Microsoft Windows " . But it seems that this code is not able to connect to the client. Please tell me how can I fix this problem .
My Server Code :
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main(){
WSADATA wsadata;
int ret;
if ((ret = WSAStartup(MAKEWORD(2, 2), &wsadata)) != 0){
cout << "Wsastartup failed" << endl;
}
else{
cout << "connection made successfully" << endl;
}
SOCKET ListeningSocket, NewConnection;
SOCKADDR_IN ServerAddr, ClientAddr;
int port = 80;
ListeningSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(port);
inet_pton(ServerAddr.sin_family,"127.0.0.1",&ServerAddr.sin_addr.s_addr);
int res= bind(ListeningSocket,(SOCKADDR*)&ServerAddr,sizeof(ServerAddr));
if (res == SOCKET_ERROR){
cout << "binding failed" << endl;
}
res = listen(ListeningSocket,5);
if (res == SOCKET_ERROR){
cout << "Listening failed" << endl;
}
int c = 1;
NewConnection= accept(ListeningSocket,(SOCKADDR*)&ClientAddr,&c);
if (NewConnection == INVALID_SOCKET){
cout << "COULD not CONNECT TO CLIENT . err code : "<<WSAGetLastError() << endl;
}
closesocket(ListeningSocket);
if (WSACleanup() == SOCKET_ERROR){
cout << "WSACleanup failed with error : " << WSAGetLastError() << endl;
}
else{
cout << "WinSock data cleaned successfully" << endl;
}
cin.get();
}
On running this code , it shows "COULD not CONNECT TO CLIENT. err code 10014" .
I've found this Description of the error code on windows dev center :
Bad address.
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).
How can I fix this error ?
When you call accept, the variable that the third parameter points to needs to hold the size of the buffer the second parameter points to. (When accept returns, it will hold the amount of space actually used)
In your code, change:
int c = 1;
to
int c = sizeof(ClientAddr);