Send Email with C++ WINSOCK (TCP, SSL) - c++

I've been trying for days to send a short, plain-text email to myself with C++. I'm using Visual Studio Express 2015. I'm eventually hoping to email automatic alerts to myself. I am using a Gmail account. I can't seem to manage to get this to work. I can send data, but can't receive. The server is closing my connection with Error 10054. (You can read about what that error means on this page.)
Here is the history: I have cobbled all this together from lots of S.O. posts and MSDN articles. I used to have a functional WSASetSocketSecurity section in this code, but for whatever reason, my connection attempts were timing out, so I omitted it. At this point, I will settle for the server not severing my connection when I send EHLO or HELO.
I'm really at a loss for how to proceed. Days of exploration, dozens of read articles, hundreds of dead ends. I hope that you'll forgive the few bits of junk code and that S.O. removed my hand alignments. Please take a look, let me know what I am doing wrong, let me know of any improper style, or anything else that offends your good-coder sensibilities. Many thanks.
#include "stdafx.h"
#include <exception>
#include <string>
#include <iostream> // In-out stream objects for development
#include <stdio.h> // Standard in-out for development
#include <winsock2.h> // For making socket connection to email server
#include <Mstcpip.h>
#include <Ws2tcpip.h> // Enhanced protocols to assist winsock2.h
#pragma comment(lib, "Ws2_32.lib") // Library for winsock2.h
#pragma comment(lib, "Fwpuclnt.lib") // Library for winsock2.h
#define BUFFER_SIZE 512
using namespace std;
void cleanup(SOCKET ConnectSocket, struct addrinfo *result) {
if (ConnectSocket != INVALID_SOCKET) {
closesocket(ConnectSocket);
}
freeaddrinfo(result);
WSACleanup();
cout << "socket closed" << endl;
cin.get(); // Development only
}
int _tmain(int argc, char* argv[]) {
// Initialize email parameters
char bccAddresses[64] = "";
char fromAddress[64] = "my_email#host.com";
char msg[512] = "Hello world!";
char port[12] = "465";
char serverName[64] = "smtp.host.com";
char toAddresses[64] = "my_email#host.com";
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo *ptr = NULL;
struct addrinfo hints;
WSADATA wsaData;
try {
// Initialize Winsock
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult == SOCKET_ERROR) {
cout << "Error " << iResult << endl;
throw std::exception("WSAStartup failed\n");
}
cout << "WSAStartup successful: " << iResult << endl;
// Set up the hints socket address structure
ZeroMemory(&hints, sizeof(hints));
hints.ai_flags = AI_SECURE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(serverName, port, &hints, &result);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("getaddrinfo failed\n");
}
cout << "getaddrinfo successful: " << iResult << endl;
// Connect to the socket
ptr = result;
ConnectSocket = WSASocket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol, NULL, 0, 0);
if (ConnectSocket == INVALID_SOCKET) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("Error at socket\n");
}
cout << "WSASocket successful: " << iResult << endl;
// Connect via the socket
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
throw std::exception("Unable to connect to server!\n");
}
cout << "connect successful: " << iResult << endl;
// Send message
char sendBuffer[BUFFER_SIZE] = "What is your malfunction";
char recvBuffer[BUFFER_SIZE];
sprintf_s(sendBuffer, BUFFER_SIZE, "EHLO %s%s", serverName, "\r\n");
iResult = send(ConnectSocket, sendBuffer, BUFFER_SIZE, 0);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK send failed\n");
}
cout << "Sent:\n" << sendBuffer << "Byte count: " << iResult << endl;
iResult = recv(ConnectSocket, recvBuffer, BUFFER_SIZE, 0);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK recv failed\n");
}
cout << "EHLO response: " << iResult << endl;
sprintf_s(sendBuffer, BUFFER_SIZE, "QUIT%s", "\r\n");
iResult = send(ConnectSocket, sendBuffer, BUFFER_SIZE, 0);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK send failed\n");
}
cout << "Sent:\n" << sendBuffer << "Byte count: " << iResult << endl;
iResult = recv(ConnectSocket, recvBuffer, BUFFER_SIZE, 0);
if (iResult < 0) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("WINSOCK recv failed\n");
}
cout << "Quit response: " << iResult << endl;
// Shutdown the connection
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
cout << "Error " << WSAGetLastError() << endl;
throw std::exception("shutdown failed\n");
}
// Clean up
cleanup(ConnectSocket, result);
return 0;
}
catch (std::exception err) {
printf(err.what());
cleanup(ConnectSocket, result);
return 1;
}
catch (...) {
printf("Unknown error\n");
cleanup(ConnectSocket, result);
return 2;
}
}

Three parts to this answer.
MIME Encode the username and password.
ACTUALLY send the username and password! :)
Some servers are skeptical and want you to say HELO or EHLO twice.
I will post full code soon. Although I feel I was about 40% of the way there, I owe my success to this site: http://www.coastrd.com/smtps.

Related

c++ socket programming: bind() fails

I'm trying to construct a simple UDP network program in C++ to establish a real-time data communication platform between two computers in my company.
The below code is for Server (receiver), and I successfully tested the network self-communication (IP='127.0.0.1').
However, if I change the IP number corresponding to another computer (147.47.42.50), I face a binding failure error.
When I type 'ping' in cmd, it successfully returns responses.
Is there any incorrect logic in my program? and is there any way to debug this problem?
#include <stdio.h>
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#pragma comment (lib,"ws2_32.lib")
#define BUFFER_SIZE 1024
using namespace std;
void main(void)
{
WSADATA wsaData;
SOCKET ServerSocket;
SOCKADDR_IN ServerInfo;
SOCKADDR_IN FromClient;
int FromClient_Size;
int Recv_Size;
int Send_Size;
int Count;
char Buffer[BUFFER_SIZE];
short ServerPort = 6000;
if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR)
{
cout << "WinSock initialization fail. " << endl;
WSACleanup();
}
memset(&ServerInfo, 0, sizeof(ServerInfo));
memset(&FromClient, 0, sizeof(FromClient));
memset(Buffer, 0, BUFFER_SIZE);
ServerInfo.sin_family = AF_INET;
ServerInfo.sin_addr.s_addr = inet_addr("147.47.42.50");
ServerInfo.sin_port = htons(ServerPort);
ServerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ServerSocket == INVALID_SOCKET) //
{
cout << "Cannot create socket." << endl;
closesocket(ServerSocket);
WSACleanup();
exit(0);
}
if (bind(ServerSocket, (struct sockaddr*)&ServerInfo,
sizeof(struct sockaddr)) == SOCKET_ERROR)
{
cout << "Bind fail." << endl;
closesocket(ServerSocket);
WSACleanup();
exit(0);
}
while (1)
{
FromClient_Size = sizeof(FromClient);
Recv_Size = recvfrom(ServerSocket, Buffer, BUFFER_SIZE, 0,
(struct sockaddr*)&FromClient, &FromClient_Size);
if (Recv_Size < 0)
{
cout << "recvfrom() error!" << endl;
exit(0);
}
cout << "Receive! client IP: " << inet_ntoa(FromClient.sin_addr) << endl;
cout << "Data: " << Buffer << endl;
}
closesocket(ServerSocket);
WSACleanup();
}

Can't send Message from Server( C++ Socket)

I'm new to C++ Socket and my Server can't send message to its client. The send() function return -1 always and it seems to have a problem with accpSocket. However Client can do that smoothly and I don't know what's wrong. Please help me thank you so much!
Server
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<iostream>
#include<sdkddkver.h>
#include<winsock.h>
using namespace std;
int main() {
SOCKET serverSocket, acceptSocket = INVALID_SOCKET;
int port = 2403;
WSADATA wsaData;
int wsaerr;
//Step 1: Set up dll
WORD versionRequested = MAKEWORD(2, 2);
wsaerr = WSAStartup(versionRequested, &wsaData);
if (wsaerr)
cout << "The winsock dll not found";
else {
cout << "The winsock dll found\n";
cout << "Winsock dll status: " << wsaData.szSystemStatus << endl;
}
//Step 2: Set up server socket
serverSocket = INVALID_SOCKET;
serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
cout << "Error at socket: " << WSAGetLastError();
WSACleanup();
return 0;
}
else
cout << "Server socket successfull!\n";
//Step 3: Binding socket
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.S_un.S_addr = INADDR_ANY;
service.sin_port = htons(port);
if (bind(serverSocket, (sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) {
cout << "Binding failed! " << WSAGetLastError();
return 0;
}
else
cout << "Binding complete!\n";
// Step 4: Listen to the connections
if (listen(serverSocket, 1) == SOCKET_ERROR) {
cout << "Listen failed! " << WSAGetLastError();
return 0;
}
else
cout << "Waiting for connections ...";
SOCKET accpSocket = accept(serverSocket, NULL, NULL);
if (accpSocket == INVALID_SOCKET) {
cout << "Accepting failed! " << WSAGetLastError();
WSACleanup();
return -1;
}
else
cout << "Accept connection!\n";
char recvMess[2000];
char sendMess[2000];
int byterecv = recv(accpSocket, recvMess, sizeof(recvMess), 0);
cout << "Client: " << recvMess << endl;
cout << "Server: ";
cin.getline(sendMess, 2000);
int bytesend = send(acceptSocket, sendMess, 2000, 0);
if (bytesend <= 0)
cout << "Unsent";
return 0;
}
Client
#include<iostream>
#include<WinSock2.h>
#include<WS2tcpip.h>
using namespace std;
int main() {
int port = 2403;
WSADATA wsaData;
int wsaerr;
SOCKET clientSocket;
WORD versionRequested = MAKEWORD(2, 2);
wsaerr = WSAStartup(versionRequested, &wsaData);
if (wsaerr)
cout << "Winsock dll not found!";
else {
cout << "Winsock dll is ok!\n";
cout << "Status: " << wsaData.szSystemStatus << endl;
}
clientSocket = INVALID_SOCKET;
clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
cout << "Set up client socket failed" << WSAGetLastError();
WSACleanup();
return 0;
}
else
cout << "Set up complete!\n";
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_port = htons(port);
if (inet_pton(clientService.sin_family, "127.0.0.1", &clientService.sin_addr) <= 0) {
cout << "Invalid address!";
return -1;
}
if ((connect(clientSocket, (SOCKADDR*)&clientService, sizeof(clientService))) == SOCKET_ERROR) {
cout << "Connection failed!\n";
WSACleanup();
return 0;
}
else
cout << "Connection complete!\n";
char sendMess[2000];
char recvMess[2000];
cout << "Client: ";
cin.getline(sendMess, 2000);
int bytesend = send(clientSocket, sendMess, 2000, 0);
int byterecv = recv(clientSocket, recvMess, 2000, 0);
if (byterecv <= 0)
cout << "Nothing";
else
cout << "Server" << recvMess << endl;
return 0;
}
int bytesend = send(acceptSocket, sendMess, 2000, 0);
is not sending to a connected socket. acceptSocket was defined at the top of main and then ignored up until the call to send
As a general rule of thumb, keep variable definition close to first use.
In the server at
SOCKET serverSocket, acceptSocket = INVALID_SOCKET;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Killlllll meeeeee!!!!
remove acceptSocket to prevent future mistakes and in
int bytesend = send(acceptSocket, sendMess, 2000, 0);
replace acceptSocket with the socket that was actually accepted, accpSocket.
Side notes:
Never ignore the return codes.
int byterecv = recv(accpSocket, recvMess, sizeof(recvMess), 0);
could fail and return -1 or return 0 if the socket was disconnected, yet the program will still
cout << "Client: " << recvMess << endl;
And worse, there's no guarantee that recvMess will be null-terminated, recv on a streaming socket gives you what the socket has available or becomes available up to the maximum number of bytes requested, so if there is any data read, make sure byterecv is a valid index in recvMess by only reading sizeof(recvMess) - 1 bytes and then forcing termination with recvMess[byterecv] = '\0'; before printing.
send(acceptSocket, sendMess, 2000, 0); sends all 2000 bytes of sendMess regardless of how many bytes were read with cin.getline(sendMess, 2000);. Use
send(acceptSocket, sendMess, cin.gcount(), 0);
instead. Add on an extra byte (cin.gcount() + 1) if you want to send the null terminator.

std::Invoke, No matching overloaded function found

I'm trying to create a thread that handles client-server communication using a socket in C++.
The program throws an error
std::Invoke, No matching overloaded function found
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(<expr>)'
I'm unable to debug the program since it crashes at startup.
Is there anything wrong in thread initialization with two parameters? Or am I missing some library, class import?
Can anyone help me out, what am I missing here?
Here's my code
#include <ws2tcpip.h>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
PCSTR IP_ADDRESS = "192.168.1.100";
#define DEFAULT_PORT "3504"
struct client_type
{
SOCKET socket;
int id;
char received_message[DEFAULT_BUFLEN];
};
int process_client(client_type& new_client);
int main();
int process_client(client_type& new_client)
{
while (1)
{
memset(new_client.received_message, 0, DEFAULT_BUFLEN);
if (new_client.socket != 0)
{
int iResult = recv(new_client.socket, new_client.received_message, DEFAULT_BUFLEN, 0);
if (iResult != SOCKET_ERROR)
cout << new_client.received_message << endl;
else
{
//cout << "recv() failed: " << WSAGetLastError() << endl;
break;
}
}
}
if (WSAGetLastError() == WSAECONNRESET)
cout << "The server has disconnected" << endl;
return 0;
}
int main()
{
WSAData wsa_data;
struct addrinfo* result = NULL, * ptr = NULL, hints;
string sent_message = "";
client_type client = { INVALID_SOCKET, -1, "" };
int iResult = 0;
string message;
cout << "Starting Client...\n";
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (iResult != 0) {
cout << "WSAStartup() failed with error: " << iResult << endl;
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
cout << "Connecting...\n";
// Resolve the server address and port
iResult = getaddrinfo(IP_ADDRESS, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
cout << "getaddrinfo() failed with error: " << iResult << endl;
WSACleanup();
system("pause");
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
client.socket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (client.socket == INVALID_SOCKET) {
cout << "socket() failed with error: " << WSAGetLastError() << endl;
WSACleanup();
system("pause");
return 1;
}
// Connect to server.
iResult = connect(client.socket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(client.socket);
client.socket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (client.socket == INVALID_SOCKET) {
cout << "Unable to connect to server!" << endl;
WSACleanup();
system("pause");
return 1;
}
cout << "Successfully Connected" << endl;
//Obtain id from server for this client;
recv(client.socket, client.received_message, DEFAULT_BUFLEN, 0);
message = client.received_message;
if (message != "Server is full")
{
client.id = atoi(client.received_message);
thread my_thread(process_client, client);
while (1)
{
getline(cin, sent_message);
iResult = send(client.socket, sent_message.c_str(), strlen(sent_message.c_str()), 0);
if (iResult <= 0)
{
cout << "send() failed: " << WSAGetLastError() << endl;
break;
}
}
//Shutdown the connection since no more data will be sent
my_thread.detach();
}
else
cout << client.received_message << endl;
cout << "Shutting down socket..." << endl;
iResult = shutdown(client.socket, SD_SEND);
if (iResult == SOCKET_ERROR) {
cout << "shutdown() failed with error: " << WSAGetLastError() << endl;
closesocket(client.socket);
WSACleanup();
system("pause");
return 1;
}
closesocket(client.socket);
WSACleanup();
system("pause");
return 0;
}```
I boiled your program down to a minimal, reproducible example:
#include <thread>
struct client_type
{
};
int process_client(client_type& new_client)
{
return 0;
}
int main()
{
client_type client;
std::thread my_thread(process_client, client);
}
This small snippet fails to compile, and trying to compile gives the error you mention.
Why does this fail? Lets look at the std::thread constructor. In the notes section we find this:
The arguments to the thread function are moved or copied by value. If
a reference argument needs to be passed to the thread function, it has
to be wrapped (e.g., with std::ref or std::cref).
And indeed std::thread my_thread(process_client, std::ref(client)); compiles without issue.

Sending and receiving data on a socket in c++

I am currently learning C++ and trying to understand sockets. I've done sockets before in high level languages in C# and Java but having problems in C++.
I've gone through the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx.
The code I have is pretty much working except there's one thing I'm not sure of. When I've written other socket apps, I don't usually receive the response until after a new line character is received.
I thought maybe C++ add 1 character received at a time and adds to the buffer, so then when I close the socket, the buffer would contain everything that was received, but it seems to be a hex value, but the hex in an ascii converter seems to print gibberish instead of the socket data.
Below is my code
const int DEFAULT_BUF_LEN = 525;
InitialiseLibrary initLibrary("tunnel.conf");
if (initLibrary.initialise(0))
{
cout << "Failed to initialise library" << endl;
}
BitsLibrary bitsLibrary;
StaticSettings staticSettings(&bitsLibrary, "tunnel.conf");
//Open a socket connection
WSAData wsaData;
int iResult;
SOCKET listenSocket = INVALID_SOCKET;
SOCKET clientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvBuf[DEFAULT_BUF_LEN];
int recBufLen = DEFAULT_BUF_LEN;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
cout << "WSAStartup Failed with error: " << iResult << endl;
return EXIT_FAILURE;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
iResult = getaddrinfo(NULL, "500", &hints, &result);
if (iResult != 0)
{
cout << "getaddrinfo failed with error: " << iResult << endl;
return EXIT_FAILURE;
}
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listenSocket == INVALID_SOCKET)
{
cout << "Socket failed with error: " << WSAGetLastError() << endl;
freeaddrinfo(result);
WSACleanup();
return EXIT_FAILURE;
}
iResult = ::bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult != 0)
{
cout << "bind failed with error: " << iResult << endl;
FreeAddrInfo(result);
closesocket(listenSocket);
WSACleanup();
return EXIT_FAILURE;
}
freeaddrinfo(result);
iResult = listen(listenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR)
{
cout << "Listen failed with error: " << WSAGetLastError() << endl;
closesocket(listenSocket);
WSACleanup();
return EXIT_SUCCESS;
}
sockaddr_in clientAddr;
socklen_t sin_size = sizeof(struct sockaddr_in);
clientSocket = accept(listenSocket, (struct sockaddr*)&clientAddr, &sin_size);
send(clientSocket, "welcome", string("welcome").length(),0);
if (clientSocket == INVALID_SOCKET)
{
cout << "accept failed with error: " << WSAGetLastError() << endl;
closesocket(listenSocket);
WSACleanup();
return EXIT_FAILURE;
}
closesocket(listenSocket);
do {
iResult = recv(clientSocket, recvBuf, recBufLen, 0);
if (iResult > 0)
{
cout << "Bytes received: " << iResult << endl;
cout << "Received: " << recvBuf << endl;
iSendResult = send(clientSocket, recvBuf, iResult, 0);
if (iSendResult == SOCKET_ERROR)
{
cout << "send failed with error: " << WSAGetLastError() << endl;
closesocket(clientSocket);
WSACleanup();
return EXIT_FAILURE;
}
cout << "Bytes sent " << iSendResult << endl;
}
else if (iResult == 0)
{
cout << "Connection closing" << endl;
}
else
{
cout << "Recv failed with error: " << WSAGetLastError() << endl;
closesocket(clientSocket);
WSACleanup();
return EXIT_FAILURE;
}
} while (iResult > 0);
iResult = shutdown(clientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
cout << "shutdown failed with error: " << WSAGetLastError() << endl;
closesocket(clientSocket);
WSACleanup();
return EXIT_FAILURE;
}
closesocket(clientSocket);
WSACleanup();
cout << "Message was: " << recvBuf << endl;
return EXIT_SUCCESS;
If I'm not mistaken, if I was doing this in C# and connect via telnet to my socket I could send Hello but the app wouldn't do anything until I sent \r\n or the buffer was full.
However, in my C++ app, as soon as I enter H my app immediately responds prints out the recvBuf which just contains H plus a load of blank characters (shows as squares in cmd) which I'm assuming is the blank parts of the array buffer, and sends the reply.
Sockets don't care about newlines or nulls. Only higher-level streaming APIs do that. The important thing is the return value of recv(). That tells you exactly how many bytes were received. Nothing in the buffer beyond that count is valid.
In a streaming protocol, it is useful to establish a protocol for determining the content length.
For example, a client could send the content-length followed by data and the server would first read the content length and then read the socket in a loop and buffer the data until content-length number of bytes have been received.

hostname not translated into an IP address using Winsock

getaddrinfo() does not translate a hostname into an IP address and consequently does not connect() to the server. Is something wrong with my implementation - compiles with no warning messages?
Is this function call to connect correct?
connect(client, result->ai_addr, result->ai_addrlen)
Full implementation listed below:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#include <iostream>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main (
int argc,
char* argv[])
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << " [hostname] [port number]\n";
exit(EXIT_FAILURE);
}
WSADATA wsaData;
WORD wVersionRequested;
int wError;
wVersionRequested = MAKEWORD(2, 2);
wError = WSAStartup(wVersionRequested, &wsaData);
if (wError != 0)
{
cerr << "WSAStartup failed with error: " << wError << endl;
exit (EXIT_FAILURE);
}
/*
* Confirm that the WinSock DLL supports 2.2.
* Note that if the DLL supports versions greater
* than 2.2 in addition to 2.2, it will still return
* 2.2 in wVersion since that is the version we
* requested.
*/
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
cerr << "Could not find a usable version of Winsock.dll." << endl;
WSACleanup();
exit(EXIT_FAILURE);
} else {
cout << "The Winsock 2.2 dll was found." << endl;
}
SOCKET client;
if ((client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
{
cerr << "Error: socket() return value == SOCKET_ERROR" << endl;
WSACleanup();
exit (EXIT_FAILURE);
}
cout << "Created a socket." << endl;
struct addrinfo *result = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if ((wError = getaddrinfo(
argv[1],
argv[2],
&hints,
&result)) !=0 )
{
freeaddrinfo(result);
WSACleanup();
if (wError == 11001)
{
cerr << "Error: occurred: getaddrinfo() failed "
<< wError << " - Host not found." << endl;
exit(EXIT_FAILURE);
}
cerr << "Error: occurred: getaddrinfo() failed "
<< wError << endl;
exit(EXIT_FAILURE);
}
/*
* Attempt to connect to the Server
*
*/
switch (wError = connect(client, result->ai_addr, result->ai_addrlen)) {
case 0:
cerr << "Resolved hostname." << endl;
break;
case SOCKET_ERROR:
wError = WSAGetLastError();
cerr << "Error: connet() failed "
"Details: " << wError << endl;
closesocket(client);
freeaddrinfo(result);
WSACleanup();
exit(EXIT_FAILURE);
break;
default:
cerr << "Fatal connect() error: unexpected "
"return value." << endl;
closesocket(client);
freeaddrinfo(result);
WSACleanup();
exit(EXIT_FAILURE);
break;
}
cout << "Connected to server." << endl;
closesocket(client);
freeaddrinfo(result);
WSACleanup();
exit(EXIT_SUCCESS);
}
getaddrinfo may be giving you an IPv6 address, or perhaps the machine has more than one IP address and you're trying to connect to the wrong one.
Also, if your server is listening on 127.0.0.1 and you try to connect to the real IP address, the connection will fail. Similarly, if the server is listening on the real IP address and you try to connect using 127.0.0.1, the connection will fail. If the server listens on 0.0.0.0, both addresses should work.
To listen on 0.0.0.0, you would have code similar to this:
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port=htons( port_num );
bind( s, (sockaddr *)&sin, sizeof( sin ) );
Try setting the hint.ai_family to AF_UNSPEC instead of AF_INET, I believe that when AF_INET is specfied the getaddrinfo functions excepts IPv4-like address.