Winsock code not working - c++

I have finished my c++ tutorial and went to winsock, but still a bit new to the subject. I made a client code that tried to connect to a website using port 80 (http) but whenever i run it i get an error code 10049 and it doesn't connect to the server. Here is the code..
Defenitions.h:
#include <iostream>
#include <winsock2.h>
using namespace std;
//Prototypes:
WORD version = MAKEWORD(2, 2);
WSADATA info;
SOCKET hSocket;
USHORT port;
sockaddr_in hSockAddr;
char website[50];
void initWSA();
void createSocket();
hostent* websiteInfo;
void getPort();
void connectSocket();
void cleanUp();
//Functions:
void initWSA(){
if(WSAStartup(version, &info) == 0){
cout << "WinSock initialization successful!" << endl;
}else{
cout << "WinSock initialization failed!" << endl;
}
}
void createSocket(){
hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(hSocket != INVALID_SOCKET){
cout << "Socket Creation Successful!" << endl;
}else{
cout << "Socket Creation Failed!" << endl;
}
}
void getPort(){
cout << "Enter the port number to connect to:" << endl;
}
void connectSocket(){
if(connect(hSocket, (SOCKADDR*)&hSockAddr, sizeof(hSockAddr)) == 0){
cout << "Connection to server successful!" << endl;
}else{
cout << "Connection to server failed! error code: " << WSAGetLastError() << endl;
}
}
void cleanUp(){
if(closesocket(hSocket) == 0){
cout << "Socket Closure Successful!" << endl;
}else{
cout << "Socket Closure Failed!" << endl;
}
if(WSACleanup() == 0){
cout << "WinSock cleanup successful!\a" << endl;
}else{
cout << "WinSock cleanup failed!\a" << endl;
}
}
main.cpp:
#include "Definitions.h"
int main(int argc, char *argv[]){
initWSA();
createSocket();
cout << "IP Address of: " << "www.google.com" << " is: "<< gethostbyname("www.google.com") << endl;
getPort();
cin >> port;
hSockAddr.sin_family = AF_INET;
hSockAddr.sin_port = htons(port);
hSockAddr.sin_addr.S_un.S_addr = inet_addr("www.google.com");
connectSocket();
cleanUp();
return 0;
}
This is always what i get:
Any suggestions?

The problem is with how you convert host address to ip,
inet_addr is for ip addresses:
The inet_addr function converts a string containing an IPv4 dotted-decimal address into a proper address for the IN_ADDR structure.
instead of:
hSockAddr.sin_addr.S_un.S_addr = inet_addr("www.google.com");
use:
struct hostent *he = gethostbyname("www.google.com");
memcpy(&hSockAddr.sin_addr, he->h_addr_list[0], he->h_length);
// Or:
//hSockAddr.sin_addr.s_addr = ((in_addr *)(he->h_addr))->s_addr;
see here: converting host to ip by sockaddr_in gethostname etc
[edit]
As Remy Lebeau has written in comment, gethostbyname is depracated and getaddrinfo should be used instead, below is sample code using getaddrinfo:
// Resolve host name
struct addrinfo hints, *servinfo, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int rv;
std::string str_port = std::to_string(port);
if ((rv = getaddrinfo("www.google.com", str_port.c_str(), &hints, &servinfo)) != 0) {
std::cerr << "getaddrinfo: " << rv << ": " << gai_strerrorA(rv) << std::endl;
return 1;
}
// Loop over all returnd addresses, first one that works is the one we want to use
for (p = servinfo; p != NULL; p = p->ai_next) {
createSocket();
if (connect(hSocket, p->ai_addr, p->ai_addrlen) == 0) {
cout << "Connection to server successful!" << endl;
break;
}
else {
cout << "Connection to server failed! error code: " << WSAGetLastError() << endl;
closesocket(hSocket);
}
}
freeaddrinfo(servinfo);

See Windows Sockets Error Codes, in this case:
WSAEADDRNOTAVAIL
10049
Cannot assign requested address.
The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0).
Did you see your IP address output? I think it's not what you want.
I think you should see this example in order to get the IP address:
Winsock Programmer’s FAQ
Examples: Get the Local IP Address(es)

Related

Why does getaddrinfo return old IP address on a VM?

I wrote an application that populates a combobox with the IP address for the Windows PC it's running on. It works except on one VMWare VM. I don't have access to the VM but was told it had been configured for a specific IP address and the owner changed that to get one dynamically. Here are the steps he followed:
Control Panel\Network and Internet\Network Connections\Change adapter settings
Select appropriate NIC and open
Select Properties
Select and open Internet Protocol Version 4 (TCP/IPV4)
VM was configured with “use the following ip address:”, I changed to Obtain an IP address automatically
Run ipconfig –release in CMD
Run ipconfig –renew in CMD
Run ipconfig\dnsflush
Restart machine
IPConfig on the VM reports the automatically assigned IP address. My code returns the previously hard coded IP. I made a console test app with my code, using getaddrinfo, and an alternate method using gethostbyname. The gethostbyname code returns new new IP, matching IPConfig.
Why does getaddrinfo return the old IP?
Where is that old value stored?
Correct way to safeguard against this behavior?
Here's the getaddrinfo code:
// the current method
void GetAI()
{
std::cout << "*** getaddrinfo ***\n";
struct addrinfo hints;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = AF_INET; // IPv4 only
hints.ai_socktype = SOCK_STREAM; // TCP socket only
hints.ai_protocol = IPPROTO_TCP; // TCP protocol only
hints.ai_flags = AI_PASSIVE; // intend to bind
char szPath[128] = "";
gethostname(szPath, sizeof(szPath));
std::cout << "Host name is " << szPath << "." << std::endl;
char* asciiPort = "";
struct addrinfo* result;
if (getaddrinfo(szPath, asciiPort, &hints, &result))
{
std::cout << "getaddrinfo call failed\n";
return;
}
struct addrinfo* rp;
int i(0);
for (rp = result; rp != NULL; rp = rp->ai_next)
{
const int BIGENOUGH = 46;
WCHAR ipstringbuffer[BIGENOUGH];
memset(ipstringbuffer, 0, BIGENOUGH);
struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*) rp->ai_addr;
std::cout << "Address " << i++ << ": " << inet_ntoa(sockaddr_ipv4->sin_addr) << std::endl;
}
}
The gethostbyname code:
// the deprecated method
int GetHBN()
{
std::cout << "*** gethostbyname ***\n";
char ac[80];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR)
{
std::cerr << "Error " << WSAGetLastError() <<
" when getting local host name." << std::endl;
return 1;
}
std::cout << "Host name is " << ac << "." << std::endl;
hostent *phe = gethostbyname(ac);
if (phe == 0)
{
std::cerr << "Bad host lookup." << std::endl;
return 1;
}
for (int i = 0; phe->h_addr_list[i] != 0; ++i)
{
in_addr addr;
memcpy(&addr, phe->h_addr_list[i], sizeof(in_addr));
std::cout << "Address " << i << ": " << inet_ntoa(addr) << std::endl;
}
return 0;
}

Error in connecting sockets in c++

I am using this code snippet from an internet website, and according to it, this code works fine. But I'm unable to connect to server. Code and error are given below:
This is the code:
#include <iostream>
#include <winsock2.h>
#include <string>
#include <conio.h>
int main()
{
WSAData version; //We need to check the version.
WORD mkword = MAKEWORD(2, 2);
int what = WSAStartup(mkword, &version);
if (what != 0){
std::cout << "This version is not supported! - \n" << WSAGetLastError() << std::endl;
}
else{
std::cout << "Good - Everything fine!\n" << std::endl;
}
SOCKET u_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (u_sock == INVALID_SOCKET)
std::cout << "Creating socket fail\n";
else
std::cout << "It was okay to create the socket\n";
//Socket address information
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("10.3.34.131");
addr.sin_port = htons(80);
/*==========Addressing finished==========*/
//Now we connect
int conn = connect(u_sock, (SOCKADDR*)&addr, sizeof(addr));
if (conn == SOCKET_ERROR){
std::cout << "Error - when connecting " << WSAGetLastError() << std::endl;
closesocket(u_sock);
WSACleanup();
}
//Send some message to remote host
char* mymsg = "success";
char vect[512] = { 0 };
int smsg = send(u_sock, mymsg, strlen(mymsg), 0);
if (smsg == SOCKET_ERROR){
std::cout << "Error: " << WSAGetLastError() << std::endl;
WSACleanup();
}
int get = recv(u_sock, vect, 512, 0);
if (get == SOCKET_ERROR){
std::cout << "Error in Receiving: " << WSAGetLastError() << std::endl;
}
std::cout << vect << std::endl;
closesocket(u_sock);
_getch();
return 0;
}
This is the error:
How can I correct this error?
Your network has no machine with IP address 10.3.34.131 that is listening on port 80. Or, if it does, that machine is rejecting your machine's connections to it.

Displaying IPv6 addresses

I am writting a program to display local IP address of the machine.
I am getting able to display IPv4 address, while getting unable to display IPv6 address.
Below is the program that i am using to display IPv4 address:
#include <iostream.h>
#include <winsock.h>
int doit(int, char **)
{
char ac[80];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
cerr << "Error " << WSAGetLastError() <<
" when getting local host name." << endl;
return 1;
}
cout << "Host name is " << ac << "." << endl;
struct hostent *phe = gethostbyname(ac);
if (phe == 0) {
cerr << "Yow! Bad host lookup." << endl;
return 1;
}
for (int i = 0; phe->h_addr_list[i] != 0; ++i) {
struct in_addr addr;
memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
cout << "Address " << i << ": " << inet_ntoa(addr) << endl;
}
return 0;
}
int main(int argc, char *argv[])
{
WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
return 255;
}
int retval = doit(argc, argv);
WSACleanup();
return retval;
}
gethostbyname is obsolete and on many systems ignores IPv6 entries.
Use modern getaddrinfo function and check ai_family member for AI_INET or AI_INET6 in order to identify address type.
As previous answer stated, use getaddrinfo(). Also, since you are using C++, make sure you use RAII for the cleanup, so cleanup will be done even if exceptions are thrown. Here is an example:
if ( (n = getaddrinfo(host.c_str(), service.c_str(), &hints, &res)) != 0) {
ostringstream ss;
ss << "getaddrinfo error for " << host << ", " << service
<< ", " << gai_strerror(n);
throw std::runtime_error(ss.str());
}
// Make sure freeaddrinfo is called even if exceptions are thrown.
// Note that we do not need to check res for NULL, unique_ptr handles that
// when deallocating.
auto cleanup = [](addrinfo* ai) { freeaddrinfo(ai); };
unique_ptr<addrinfo, decltype(cleanup)> aip(res, cleanup);

TCP/IP server in C++ is not waiting for client

I found some code in the internet with some basics about creating an TCP/IP server in C++.
I took this code, added some libraries and some lines of code. The result is, that I am able to compile and run the code/server in Qt Creator on Windows as a console program. Nevertheless I am not able to connect to the server because it just runs through the code without waiting and accepting a connection from an TCP client.
This is the code:
EDIT: Code is updated and it's now working. Test against == -1 is the solution.
#define PORT 2000
#define MAX_QUEUE 5
#define BUF_SIZE 1024
int main(int argc, char* const argv[])
{
cout << "Hello World!" << endl;
WSADATA wsaData;
int wsaret = WSAStartup(MAKEWORD( 4, 4 ), &wsaData);
cout << "wsaret: " << wsaret << endl;
cout << "Start TCP/IP Server" << endl;
/* file descriptors for sockets */
SOCKET sock_1, sock_2; //switched from in to SOCKET //unsigned int sock_1, sock_2;
int rec_value, length;
char buf[BUF_SIZE];
//struct sockaddr_in server;
struct sockaddr_in server;
/* create stream socket in internet domain*/
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//if(sock_1 < 0)
if(sock_1 == -1)
{
cout << "socket: " << WSAGetLastError() << endl; //instead of //cout << "socket: " << strerror(errno) << endl; //cout << "socket wsaret: " << wsaret << endl;
exit(1);
}
/* build address in internet domain */
server.sin_family = AF_INET;
/* everyone is allowed to connet to server */
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129");
server.sin_port = htons(2000); //server.sin_port = PORT; //Port: 2000
/* bind socket */
//if(bind(sock_1, (struct sockaddr *)&server, sizeof(server)));
int bindreturn = (bind(sock_1, (struct sockaddr *)&server, sizeof(server)));
if(bindreturn == -1)
{
cout << "bind: " << WSAGetLastError() << endl; //instead of //cout << "bind: " << strerror(errno) << endl; //cout << "bind wsaret: " << wsaret << endl;
exit(1);
}
listen(sock_1,MAX_QUEUE);
/* start accepting connection */
sock_2 = accept(sock_1,0,0);
if(sock_2 < 0)
{
cout << "accept: " << WSAGetLastError() << endl;
exit(1);
}
/* read from sock_2 */
while(rec_value=recv(sock_2,buf,BUF_SIZE,0))
{
if(rec_value < 0)
{
cout << "recv: " << WSAGetLastError() << endl;
exit(1);
}
else
{
cout << "else" << endl;
send(sock_2,"1,2,3",strlen("1,2,3"),0);
}
}
cout << "Ending connection" << endl;
closesocket(sock_1);
closesocket(sock_2);
cout << "End TCP/IP Server" << endl;
WSACleanup();
return 0;
}
The console shows the following after/during running the program in one or less seconds:
Hello World!
wsaret: 0
Start TCP/IP Server
bind: 0
What can I do, that the server waits for an connection partner?
Thanks in advance.
Regards
matl
Edit: Added a few lines of code at the beginning, which I forgot before.
Edit: Code update
Edit: Code update
I'm going to comment in detail on the original code you posted.
cout << "Start TCP/IP Server" << endl;
//int sock_1,sock_2; /* file descriptors for sockets */
int sock_1, sock_2;
int rec_value, length;
char buf[BUF_SIZE];
//struct sockaddr_in server;
sockaddr_in server;
/* create stream socket in internet domain*/
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//0);
Missing test here. You must test the result for -1 along these lines:
if (sock_1 == -1)
{
cout << "socket creation error: " << WSAGetLastError() << endl;
exit(1); // or some other measure to prevent continuation
}
Back to your code:
/* build address in internet domain */
server.sin_family = AF_INET;
/* everyone is allowed to connet to server */
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129");
server.sin_port = PORT; //Port: 2000
That should be
server.sin_port = htons(PORT);
Back to your code:
/* bind socket */
int bindreturn = bind(sock_1, (struct sockaddr *)&server, sizeof(server));
cout << "bindreturn: " << bindreturn << endl;
Inadequate. Here again you need to test for -1, and print WSAGetLastError() and exit if you got it.
listen(sock_1,MAX_QUEUE);
Untested. Here again you need to test for -1 etc.
/* start accepting connection */
//system("pause");
sock_2 =accept(sock_1,0,0);
//system("pause");
cout << "acceptreturn: " << sock_2 << endl;
Inadequate again, see above.
/* read from sock_2 */
while(rec_value=recv(sock_2,buf,BUF_SIZE,0))
{
if(rec_value<0)
{
cout << "error: " << rec_value << endl;
exit(1);
}
Test is incorrect. A system call indicates error by returning exactly -1, not just any value < 0. A socket FD for example returned by socket() or accept() can be negative, or any value other than -1.
else
{
cout << "else" << endl;
send(sock_2,"1,2,3",strlen("1,2,3"),0);
}
}
closesocket(sock_1);
closesocket(sock_2);
cout << "End TCP/IP Server" << endl;
return 0;
It is apparent from the closesocket() calls that you're using Winsock, in which case both WSAStart() and WSACleanup() are missing.
How is PORT defined?
You should use:
server.sin_port = htons(PORT); //Port: 2000
Is your IP-address correct?
All your calls are receiving SOCKET_ERROR (-1), so you should check lasterror to get more information.
Not sure (on Windows here), but shouldn't those be unsigned int's?
int sock_1, sock_2;
Update:
Ok, you seem to be using Qt on Windows.
For Qt, you might as well use the Qt libraries.
On Windows in general, you could use the free MS Visual Studio.
You also need to call WSAStartup() like this:
WSADATA wsaData;
int wsaret = WSAStartup(MAKEWORD( 4, 4 ), &wsaData);
// check wsaret
// more code here
WSACleanup();
Also use SOCKET:
SOCKET sock_1, sock_2;
Check the errorcodes with WSAGetLastError().

C++ Socket Receiving Erroneous Commands, not intended ones

I am learning socket programming for use in an upcoming project, and I have researched the issue pretty extensively. Basically, all this program needs to is on a client computer (locally, i.e. my computer) needs to connect to a remote server and send a command (which it has done, I have gotten it to read back Apache server stats to me).
What is happening is this: I believe I have the socket set right, but the server receives random garbage buffers (one of which consisted of " '>Z"). I have tried various socket settings, different bindings, etc.
I have in the process of starting it will initialize winsock, create a socket, bind the network, and then do a listen loop and while(1) recv data.
I have yet to get the server (on a remote computer, hosted at a datacenter) to output the message. This is my only goal for the time being. I appreciate everyone's help in advance, and the code is before (this is the entire code, sorry for the length).
Client Code:
char *host = "127.0.0.1";
SOCKET clientsock;
struct sockaddr_in server_address;
struct hostent *host_info;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != -1) {
cout << "WINSOCK2 Initialized" << endl;
if((clientsock = socket(AF_INET, SOCK_STREAM, 0)) != SOCKET_ERROR) {
cout << "Socket Created" << endl;
char opt[2];
opt[0] = 0;
opt[1] = 1;
//setsockopt(clientsock, SOL_SOCKET, SO_BROADCAST, opt, sizeof(opt));
host_info = gethostbyname(host);
server_address.sin_family = AF_INET;
server_address.sin_addr = *((struct in_addr *)host_info->h_addr);
server_address.sin_port = htons(80);
if(connect(clientsock, (struct sockaddr *)&server_address, sizeof(struct sockaddr)) == 0) {
cout << "Connected to host" << endl;
char COMMAND[22] = "SVR --WINSOCK-VERIFY\0";
if(send(clientsock, COMMAND, sizeof(COMMAND), 0)) {
cout << "Command Sent" << endl;
closesocket(clientsock);
}
else {
cout << "ERROR - Could not send command. " << "Error: " << WSAGetLastError() << endl;
closesocket(clientsock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not connect to host. " << "Error: " << WSAGetLastError() << endl;
closesocket(clientsock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not create the socket. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
}
else {
cout << "ERROR - Could not initialize WINSOCK2. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
Server Code:
SOCKET serversock;
char *server = "127.0.0.1";
//char *server = "50.31.1.180";
struct sockaddr_in server_address;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != -1) {
cout << "WINSOCK2 Initialized" << endl;
if((serversock = socket(PF_INET, SOCK_DGRAM, PF_UNSPEC)) != SOCKET_ERROR) {
cout << "Socket Created" << endl;
unsigned long NB = 1;
ioctlsocket(serversock, FIONBIO, &NB);
server_address.sin_family = AF_INET;
server_address.sin_addr = *((struct in_addr *)server);
server_address.sin_port = htons(21578);
if(bind(serversock, (struct sockaddr*)&server_address, sizeof(struct sockaddr) == 0)) {
cout << "Network bound" << endl;
cout << "Listening..." << endl;
listen(serversock, 5);
while(1) {
int size = sizeof((struct sockaddr *)server);
SOCKET clientsock = accept(serversock, (struct sockaddr *)server, &size);
char INCOMMAND[20];
if(clientsock >= 0) {
if(recv(clientsock, INCOMMAND, sizeof(INCOMMAND), 0)) {
int i = 0;
if(INCOMMAND == "SVR --WINSOCK-VERIFY\0") {
cout << "SVR receieved" << endl;
}
while(INCOMMAND[i] != '\0') {
cout << INCOMMAND[i];
i++;
}
cout << endl;
}
else {
cout << "ERROR - Could not receive command" << endl;
break;
}
}
}
}
else {
cout << "ERROR - Could not bind network. " << "Error: " << WSAGetLastError() << endl;
closesocket(serversock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not create the socket. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
}
else {
cout << "ERROR - Could not initialize WINSOCK2. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
Calls to send/recv may not send/receive the amount of bytes you indicate in their third argument, in fact, most of the time they will send/receive less bytes than you expect. You usually have to loop until the entire data has been sent/received. Also note that doing this:
char buffer[100];
recv(clientsock, buffer, sizeof(buffer), 0);
cout << buffer;
Will most surelly print garbage, since you don't have a null terminator in your char array(whatch out for buffer overflows when appending it), and you're not checking the return value of recv. It might be reading 1 byte only(or none if an error ocurred). You're printing your buffer the same way in your server app.
In this case, you are actually sending the null-terminator, but since you might read less bytes than you expect, this character might not be received by the other application, thus printing it will print garbage chars.
Edit: You should have a look at the structure of a sockaddr struct. You can have a look at it here. In your code you are using this convertion:
int size = sizeof((struct sockaddr *)"127.0.0.1");
const char *, which is the type of "127.0.0.1", cannot be casted to a sockaddr pointer, they're incompatible. Here you should use getaddrinfo in order to resolve the IP address(note that you could use a domain name, and this function would resolve it). There are lots of tutorials online on how to use this function, just search for "getaddrinfo".