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);
Related
I need to receive a HTTP request from my browser, when I run localhost:8228 it works fine, I receive the header in the buffer and am able to write it to the console and even echo send it back to the browser. But when I try reading a request from a actual webpage, buffer is empty, it prints nothing.
I have a simple main that looks like this:
int main (int argc, char *argv[]) {
char buffer[1024*1024] = {0};
int port_number = 8228;
if (argc == 1)
std::cout << "Using default port number, 8228." << std::endl;
else if (argc == 3) {
port_number = atoi(argv[2]);
} else {
std::cout << "::Error::" << std::endl;
std::cout << "Wrong number of arguments." << std::endl;
exit[0];
}
AppSocket app;
app.Start((int)port_number);
app.AcceptCall();
int request_size = app.ReceiveRequest(buffer, sizeof(buffer));
return 0;
}
My AppSocket functions would be:
void AppSocket::Start(int port) {
// Create a socket
listening_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listening_fd == -1) {
std::cerr << "Could not create a socket." << std::endl;
exit(-1);
}
app_hint.sin_family = AF_INET;
app_hint.sin_port = htons(port);
inet_pton(AF_INET, "127.0.0.1", &app_hint.sin_addr);
if (bind(listening_fd, (sockaddr*)&app_hint, sizeof(app_hint))< 0) {
std::cerr << "Cannot bind to IP/port." << std::endl;
exit(-2);
}
std::cout << "Socket has been bound." << std::endl;
if (listen(listening_fd, SOMAXCONN) == -1) {
std::cerr << "Cannot listen." << std::endl;
exit(-3);
}
std::cout << "Listening to port " << port << std::endl;
std::cout << "Your socket is: " << listening_fd << std::endl;
}
void AppSocket::AcceptCall() {
client_size = sizeof(client_addr);
client_fd =
accept(listening_fd, (sockaddr *)&client_addr, &client_size);
if (client_fd < 0) {
std::cerr << "Error connecting to client." << std::endl;
exit(-4);
}
std::cout << inet_ntoa(client_addr.sin_addr)
<< " connected to port "
<< ntohs(client_addr.sin_port) << std::endl;
close(listening_fd);
}
int AppSocket::ReceiveRequest(char *buffer, int max) {
std::cout << "Client is: " << client_fd << std::endl;
memset(buffer, 0, buff_size); //clear buffer
int n = recv(client_fd, buffer, buff_size, 0);
if (n < 0)
std::cerr << "A connection issue has occured." << std::endl;
if (n == 0)
std::cout << "Client disconected." << std::endl;
std::cout << "recv return " << n << std::endl;
std::cout << buffer << std::endl;
return n;
}
When I run and access a webpage I get this:
Using default port number, 8228.
Socket has been bound.
Listening to port 8228
Your socket is: 3
127.0.0.1 connected to port 37522
Client is: 4
recv return 3
None of the questions I've read seem to work for me...
edit: sorry one of the lines in the main code wasn't copied.
How can I receive repeatedly? A while loop? I tried that and just kept receiving nothing.
The code works, what was happening is that the firefox proxy settings were wrong, when I ran localhosts it worked fine because it was actually working as the server due to the port it was using but when trying to access a "real" website it didn't. After configuring it correctly it did just what it's supposed to do.
I'm trying to implement my own server and client side which uses sockets to send and receive data. But i got some problem with realization of multi-threading.
My server.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
using namespace std;
void connection_handler(int socket) {
char client_message[256];
memset(&client_message, 0, 256);
size_t message_size = 0;
while ((message_size = recv(socket, client_message, sizeof(client_message) - 1, 0)) > 0) {
client_message[message_size] = '\0';
cout << "[Server] Client message accepted" << endl;
cout << "[Server] Client message: " << client_message << endl;
if (write(socket, client_message, message_size) == -1) {
cout << "[Client] Message sending failed" << endl;
return;
}
cout << "[Server] Message sent to client" << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
memset(&client_message, 0, 256);
}
}
int main() {
unsigned short int PORT = 8080;
int listener, client_socket;
socklen_t client_len;
struct sockaddr_in server_address{};
memset(&server_address, 0, sizeof(server_address));
listener = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
if (inet_aton("127.0.0.1", &server_address.sin_addr) == 0) {
cout << "[Server] Invalid IP address" << endl;
return -1;
}
if (bind(listener, (struct sockaddr*) &server_address, sizeof(server_address)) == -1) {
cout << "[Server] Binding failed" << endl;
return -1;
}
cout << "[Server] All setting are done" << endl;
cout << "[Server] Server enabled" << endl;
if (listen(listener, 100) == -1) {
cout << "[Server] Listening failed" << endl;
return -1;
}
cout << "[Server] Waiting for connection..." << endl;
for (; ;) {
client_socket = accept(listener, (struct sockaddr*) &server_address, &client_len);
cout << "[Server] Connection accepted" << endl << endl;
cout << "----------------------------" << endl << endl;
int new_socket = client_socket;
thread handling_thread(connection_handler, new_socket);
handling_thread.detach();
}
}
My client.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
int main() {
unsigned short int PORT = 8080;
int sockfd;
char buffer[256] = {0};
struct sockaddr_in server_address{};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
if (connect(sockfd, (struct sockaddr*) &server_address, sizeof(server_address)) < 0) {
cout << "[Client] Connection failed" << endl;
return -1;
}
cout << "[Client] All setting are done" << endl;
cout << "[Client] Succefully connected to server" << endl << endl;
cout << "----------------------------" << endl << endl;
while (true) {
string client_request;
cout << "[Client] Enter a message: ";
getline(cin, client_request);
if (client_request == "-1") {
write(sockfd, client_request.c_str(), client_request.size());
close(sockfd);
cout << endl << "[Client] Client exited" << endl;
return 0;
}
if (write(sockfd, client_request.c_str(), client_request.size()) == -1) {
cout << "[Client] Message sending failed" << endl;
}
cout << "[Client] Message sent to server" << endl;
memset(&buffer, 0, 256);
read(sockfd, buffer, 256);
cout << "[Client] Server message: " << buffer << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
}
}
It's perfectly working until i create one more connection to server and after that second client cans send and receive data, but first one at this time becomes not working.
I compiled my program like this: g++ server.cpp -lpthread -o server -std=c++11 And then in other console tab run my compiled client.cpp: ./client.
To check multi-threading working i run client one more time (in other tab again) and trying send requests in two tabs at the same time.
I want to realize multi-threading in my program. How can i do this?
UPD: I'm using Linux
UPD2: Problem solved. Fixed code there.
int new_socket = client_socket;
thread handling_thread(connection_handler, &new_socket);
handling_thread.detach();
}
This initializes new_socket, which gets declared in local scope inside this for loop, then passes the pointer to this new_socket to a new thread that gets started, and detached. Immediately after that, this for loop iteration ends, which destroys the new_socket object, before starting the next iteration of this loop.
Meanwhile, the execution thread repeatedly attempts to dereference the int * it receives, which now points to a destroyed object. This results in undefined behavior, and the likely reason your program is "not working".
The most simple solution is to create the int socket value in dynamic scope, using new, and then pass the pointer to this newed socket value to the execution thread. The execution thread will, of course, be responsible for retrieving the socket value, then properly deleteing it, to avoid leaking memory.
This should be sufficient for this simple program. More complicated programs will likely require slightly more sophisticated socket and dynamic scoping handling logic, for reliability.
// In server.cpp after connection has established
std::string input;
input.reserve(5);
std::cout << "Enter message to send: ";
std::cin.ignore(); // =====(1)=====
std::getline(std::cin, input);
std::cout << "Sending..." << std::endl;
auto len = input.length();
auto bytes_sent = send(newFD, input.data(), len, 0); // =====(2)=====
std::cout << "Input length : " << input.length() << std::endl
<< "Input bytes sent : " << bytes_sent << std::endl;
My aim is to use std::string instead of plain old char[fixed] in simple tcp client server program. So in server.cpp I have 2 doubts. So far my initial guesses are working as expected. I've marked them above in code.
cin.ignore() vs cin.clear() + cin.sync()
std::string.data() vs std::string.c_str()
Which should I use? I'm not even sure of the difference b/w any of these and I don't know if they're contributing to my problem.
// In client.cpp
std::string message;
message.reserve(5);
auto len = message.capacity();
auto bytes_recv = recv(sockFD, &message.front(), len - 1, 0); // =====(1)=====
message[len] = 0; // =====(2)=====
close(sockFD);
freeaddrinfo(res);
std::cout << "Bytes recieved :" << bytes_recv << std::endl;
std::cout << message.c_str() << std::endl; // =====(3)=====
And in client.cpp, everything goes wrong when I try to send bigger strings. But I probably know the cause, however solution is somewhat tricky to implement.
Am I doing right thing to pass &std::string.front() to write incoming data?
This is wrong, string class should manage this, right? However since I'm directly writing to &front(), I guess length won't get updated or I'm not sure what happens but data surely gets lost when outputting with std::cout << message;.
I'm doing this just because I'm directly writing to &front, still it produces garbage if somehow data returned is smaller than total length, probably because it cannot find terminating character at right place?
server.cpp
// compile as 'g++ server.cpp -o server.app -std=c++14'
// run as : './server.app 8080'
#include <iostream>
#include <string>
#include <cstring>
extern "C" {
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cerr << "Run program as 'program port'" << std::endl;
return -1;
}
auto &portNum = argv[1];
const unsigned int backLog = 5;
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int gAddRes = getaddrinfo(NULL, portNum, &hints, &res);
if(gAddRes != 0) {
std::cerr << gai_strerror(gAddRes) << std::endl;
return -2;
}
std::cout << "Detecting addresses" << std::endl;
unsigned int numOfAddr = 0;
char ipStr[INET6_ADDRSTRLEN];
for(p = res; p != NULL; p = p->ai_next) {
void *addr;
std::string ipVer = "IPv0";
if(p->ai_family == AF_INET) {
ipVer = "IPv4";
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
++numOfAddr;
}
else {
ipVer = "IPv6";
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
++numOfAddr;
}
inet_ntop(p->ai_family, addr, ipStr, sizeof(ipStr));
std::cout << "(" << numOfAddr << ") " << ipVer << " : " << ipStr
<< std::endl;
}
if(!numOfAddr) {
std::cerr << "Found no host address to use" << std::endl;
return -3;
}
std::cout << "Enter the number of host address to bind with:" << std::endl;
unsigned int choice = 0;
bool madeChoice = false;
do {
std::cin >> choice;
if(choice > (numOfAddr + 1) || choice < 1) {
madeChoice = false;
std::cout << "Wrong choice, try again!" << std::endl;
}
else
madeChoice = true;
} while(!madeChoice);
p = res;
bool isIPv4 = true;
if(choice > 1) {
unsigned int temp = 1;
while(choice < temp) {
p = p->ai_next;
++temp;
}
if(p->ai_family == AF_INET) {
isIPv4 = true;
}
else
isIPv4 = false;
}
int sockFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(sockFD == -1) {
std::cerr << "Error while creating socket" << std::endl;
freeaddrinfo(res);
return -4;
}
int bindR = bind(sockFD, p->ai_addr, p->ai_addrlen);
if(bindR == -1) {
std::cerr << "Error while binding socket" << std::endl;
close(sockFD);
freeaddrinfo(res);
return -5;
}
int listenR = listen(sockFD, backLog);
if(listenR == -1) {
std::cerr << "Error while Listening on socket" << std::endl;
close(sockFD);
freeaddrinfo(res);
return -6;
}
struct sockaddr_storage client_addr;
socklen_t client_addr_size = sizeof(client_addr);
int newFD =
accept(sockFD, (struct sockaddr *)&client_addr, &client_addr_size);
if(newFD == -1) {
std::cerr << "Error while Accepting on socket" << std::endl;
close(sockFD);
freeaddrinfo(res);
return -7;
}
std::string input;
input.reserve(5);
std::cout << "Enter message to send: ";
std::cin.ignore();
std::getline(std::cin, input);
std::cout << "Sending..." << std::endl;
auto len = input.length();
auto bytes_sent = send(newFD, input.data(), len, 0);
std::cout << "Input length : " << input.length() << std::endl
<< "Input bytes sent : " << bytes_sent << std::endl;
close(newFD);
close(sockFD);
freeaddrinfo(res);
return 0;
}
client.cpp
// compile as 'g++ client.cpp -o client.app -std=c++14'
// run as : './client.app 0 8080'
#include <iostream>
#include <cstring>
extern "C" {
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
}
int main(int argc, char *argv[])
{
if(argc != 3) {
std::cerr << "Run program as 'program ipaddress port'" << std::endl;
return -1;
}
auto &ipAddress = argv[1];
auto &portNum = argv[2];
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int gAddRes = getaddrinfo(ipAddress, portNum, &hints, &res);
if(gAddRes != 0) {
std::cerr << gai_strerror(gAddRes) << std::endl;
return -2;
}
std::cout << "Detecting addresses" << std::endl;
unsigned int numOfAddr = 0;
char ipStr[INET6_ADDRSTRLEN];
for(p = res; p != NULL; p = p->ai_next) {
void *addr;
std::string ipVer = "IPv0";
if(p->ai_family == AF_INET) {
ipVer = "IPv4";
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
++numOfAddr;
}
else {
ipVer = "IPv6";
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
++numOfAddr;
}
inet_ntop(p->ai_family, addr, ipStr, sizeof(ipStr));
std::cout << "(" << numOfAddr << ") " << ipVer << " : " << ipStr
<< std::endl;
}
if(!numOfAddr) {
std::cerr << "Found no host address to use" << std::endl;
return -3;
}
std::cout << "Enter the number of host address to bind with:" << std::endl;
unsigned int choice = 0;
bool madeChoice = false;
do {
std::cin >> choice;
if(choice > (numOfAddr + 1) || choice < 1) {
madeChoice = false;
std::cout << "Wrong choice, try again!" << std::endl;
}
else
madeChoice = true;
} while(!madeChoice);
p = res;
bool isIPv4 = true;
if(choice > 1) {
unsigned int temp = 1;
while(choice < temp) {
p = p->ai_next;
++temp;
}
if(p->ai_family == AF_INET) {
isIPv4 = true;
}
else
isIPv4 = false;
}
int sockFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(sockFD == -1) {
std::cerr << "Error while creating socket" << std::endl;
return -4;
}
int connectR = connect(sockFD, p->ai_addr, p->ai_addrlen);
if(connectR == -1) {
close(sockFD);
std::cerr << "Error while connecting socket" << std::endl;
return -5;
}
std::string message;
message.reserve(5);
auto len = message.capacity();
auto bytes_recv = recv(sockFD, &message.front(), len - 1, 0);
message[len] = 0;
close(sockFD);
freeaddrinfo(res);
std::cout << "Bytes recieved :" << bytes_recv << std::endl;
std::cout << message.c_str() << std::endl;
return 0;
}
Your question on this is too vague to provide a helpful answer.
data() and c_str() are effectively the same thing since C++11. It doesn't matter which one you use. EDIT: In C++17, data() will have a non-const overload that returns a non-const char*, so you will not need to do &message.front() to access a modifiable form of the underlying buffer. c_str() will remain const.
&message.front() is right... and wrong. That is the way to get a non-const char* to the contents of your std::string. BUT message is uninitialized and has a size() of 0 at that point in the code, so I'm not even sure that line of code is well-defined behavior. Rather than doing a reserve(5) I would construct your string like this: auto message = std::string(5, ' '); Then when you pass it into recv there will actually be valid stuff there for it to overwrite and you'll be able to read it from message afterwards.
Yes, this is wrong. You should be setting your string up to be the actual size you need. I suspect you can just pass in len instead of len - 1 if you do this. On this topic, are you certain everything you'll ever receive is only 4 bytes long? Or are you intentionally only reading 4 bytes at a time?
a) you don't need to pass c_str() to std::cout. << is overloaded to accept std::string as well. b) recv returns the number of bytes that you received. If that value is less than the size you initialized your message to, then the remaining characters in your string will be garbage (or ' ' chars if you followed my advice re:#3). I would do message.resize(bytes_recv); after receiving the message.
Your questions have been addressed by caps,, but my 2 cents. What about having your own send/recv functions and hiding the complexity?
For example along the lines of:
ssize_t recv(int sockfd, std::string &buf, size_t len, int flags) {
buf.resize(len); // current status unknown -> make it fit
ssize_t n = ::recv(sockfd, (void *)buf.data(), len, flags);
buf.resize(n >= 0 ? n : 0); // take error into account
return n;
}
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)
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".