boost udp receiver on windows and linux - sockets

I have a simple udp application written using boost:asio, where udp unicast receiver runs on windows and unicast sender runs on linux . My unicast sender on linux sent the packet successfully , but reciver on windows does not any packets , but I could see that packets sent by sender on wireshark which is running on windows . below is my udp receiver code (which is based on the sample provided my boost libs).
class unicast_Receiver
{
public:
unicast_Receiver(boost::asio::io_service& io_service, boost::asio::ip::udp::endpoint end1)
: socket_(io_service)
{
socket_.open(boost::asio::ip::udp::v4());
//socket_.open(end1.protocol());
socket_.bind(end1);
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
std::cout << " >> on " <<socket_.local_endpoint()<<" :: #" << __LINE__ << __FUNCTION__ <<std::endl;
start_receive();
}
private:
void start_receive()
{
std::cout << "\n !!!!Waiting in the Unicast Data Receive >> on " << Unicastlisten_endpoint_ <<" :: #" << __LINE__ << __FUNCTION__ <<std::endl;
socket_.async_receive_from(
boost::asio::buffer(data_, max_length), remote_endpoint_,
boost::bind(&unicast_Receiver::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_receive(const boost::system::error_code& error,
std::size_t /*bytes_transferred*/)
{
if (!error || error == boost::asio::error::message_size)
{
std::cout << "Unicast Data Received >> " <<"<< #" << __LINE__ << __FUNCTION__ <<std::endl;
std::cout << "\n" << data_ << "\n";
memset(data_,0,max_length);
start_receive();
}
}
void handle_send(boost::shared_ptr<std::string> /*message*/,
const boost::system::error_code& /*error*/,
std::size_t /*bytes_transferred*/)
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
enum { max_length = 1024 };
char data_[max_length];
boost::array<char, 1> recv_buffer_;
};
int main(int argc, char* argv[])
{
boost::asio::io_service io_serviceSe;
boost::asio::ip::udp::endpoint Unicastlisten_endpoint_(boost::asio::ip::address::from_string(argv[1]),atoi(argv[2]));
unicast_Receiver server(io_serviceSe,Unicastlisten_endpoint_);
}

Related

Segmentation Error: Help on the correct allocation memory when saving & loading binary files containing a specific structure from a class

This is my first time asking a question, so apologies if it is not done 100%:
I have a class which saves and loads a binary file with a specific data structure.
If the program creates an instance of the class, save the binary file, and creates another instance of the class to load/read the binary file consequently, everything seems 100% correct.
However, if I run the program to save the binary file and then run it again to load/read that binary file, it gives me a segmentation fault at the end.
The program still does everything it needs to do before the segmentation fault, except deconstructing the class at the end (obviously).
It looks like my allocation of the memory is not correct, but I am not sure where I am going wrong.
A simplified version of the code follow (also here: https://github.com/LenteDreyer/Tests.git )
Can someone see where I am going wrong?
class header file that save/loads the file
#ifndef __TESTS_MAP_HH__
#define __TESTS_MAP_HH__
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
typedef struct test_struct{
bool test_bool;
double test_double;
std::vector<double> test_vector;
} test_struct_t;
class map
{
private:
std::string m_path, m_str;
double m_double;
test_struct m_struct;
public:
map(const std::string& a_id);
void set_str(std::string a_str);
void set_double(double a_double);
void set_struct(test_struct a_struct);
void load_file();
void save_file() const;
void show_file() const;
~map();
};
#endif //__TESTS_MAP_HH__
class source file that save/loads the binary file
#include "map.hh"
map::map(const std::string& a_id)
{
m_path = a_id + ".bin";
m_str = "none";
m_double = 0.0;
m_struct = {false, 0.0};
}
void map::set_str(std::string a_str){
m_str = a_str;
}
void map::set_double(double a_double){
m_double = a_double;
}
void map::set_struct(test_struct a_struct){
m_struct = a_struct;
}
void map::load_file(){
std::ifstream l_inF;
l_inF.open(m_path.c_str(), std::ios::binary | std::ios::in);
l_inF.read((char*)&m_double,sizeof(double));
l_inF.read((char*)&m_struct,sizeof(test_struct_t));
size_t str_size;
l_inF.read((char*)&str_size, sizeof(str_size));
m_str.resize(str_size);
l_inF.read((char*)&m_str[0], str_size);
l_inF.close();
}
void map::save_file() const{
std::ofstream l_outF;
l_outF.open(m_path.c_str(), std::ios::binary | std::ios::out);
l_outF.write((char*)&m_double,sizeof(double));
l_outF.write((char*)&m_struct,sizeof(test_struct_t));
size_t str_size = m_str.size();
l_outF.write((char*)&str_size, sizeof(str_size));
l_outF.write((char*)&m_str[0], str_size);
l_outF.close();
}
void map::show_file() const{
std::cout << ">>-----------------------------------------------" << std::endl;
std::cout << ">> double : " << m_double << std::endl;
std::cout << ">> double : " << m_double << std::endl;
std::cout << ">> struct.bool : " << m_struct.test_bool << std::endl;
std::cout << ">> struct.double : " << m_struct.test_double << std::endl;
std::cout << ">> struct.vector : " << "size = " << m_struct.test_vector.size() << std::endl;
std::cout << ">> string : " << m_str << std::endl;
std::cout << ">>-----------------------------------------------" << std::endl;
}
map::~map(){}
main function case 1 works, and case 2 gives the segmentation fault.
#include "map.hh"
int main(int argc, char const *argv[])
{
std::string id = "mapfile";
int action = 0;
if(argc > 1) action = std::stoi(argv[1]);
else {
std::string input;
std::cout << "Enter case (1 or 2): ";
std::cin >> input;
action = std::stoi(input);
}
switch (action)
{
case 1:
{
// This works 100% (no errors and it saves/reads class perfectly)
std::vector<double> l_vect = {0.1, 0.0, 0.6};
test_struct save_struct = {true, 5.0, l_vect};
map test_save(id);
test_save.show_file();
test_save.set_double(8.0);
test_save.set_str("save this string");
test_save.set_struct(save_struct);
test_save.show_file();
test_save.save_file();
map test_load(id);
test_load.load_file();
test_load.show_file();
}
break;
case 2:
{
// gives segmentation error at the end of the program
map test_load(id);
test_load.load_file();
test_load.show_file();
}
break;
default:
break;
}
return 0;
}

How to configure UDP endpoints when client an server are running on different machines connected over P2P connection

I am able communicate UDP packets between a Client and Server running on localhost basically using the below code.
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <thread>
#include <iostream>
#define IPADDRESS "127.0.0.1"
#define UDP_PORT 13251
using boost::asio::ip::udp;
using boost::asio::ip::address;
void Sender(std::string in) {
boost::asio::io_service io_service;
udp::socket socket(io_service);
udp::endpoint remote_endpoint = udp::endpoint(address::from_string(IPADDRESS), UDP_PORT);
socket.open(udp::v4());
boost::system::error_code err;
auto sent = socket.send_to(boost::asio::buffer(in), remote_endpoint, 0, err);
socket.close();
std::cout << "Sent bytes" << sent << "\n";
}
struct Client {
boost::asio::io_service io_service;
udp::socket socket{io_service};
boost::array<char, 1024> recv_buffer;
udp::endpoint remote_endpoint;
int count = 3;
void handle_receive(const boost::system::error_code& error, size_t bytes_transferred) {
if (error) {
std::cout << "Receive failed: " << error.message() << "\n";
return;
}
std::cout << "Received: '" << std::string(recv_buffer.begin(), recv_buffer.begin()+bytes_transferred) << "' (" << error.message() << ")\n";
if (--count > 0) {
std::cout << "Count: " << count << "\n";
wait();
}
}
void wait() {
socket.async_receive_from(boost::asio::buffer(recv_buffer),
remote_endpoint,
boost::bind(&Client::handle_receive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void Receiver()
{
socket.open(udp::v4());
socket.bind(udp::endpoint(address::from_string(IPADDRESS), UDP_PORT));
wait();
std::cout << "Receiving\n";
io_service.run();
std::cout << "Receiver exit\n";
}
};
int main(int argc, char *argv[])
{
Client client;
std::thread r([&] { client.Receiver(); });
std::string input = argc>1? argv[1] : "hello world";
std::cout << "Input is '" << input.c_str() << "'\nSending it to Sender Function...\n";
for (int i = 0; i < 3; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
Sender(input);
}
r.join();
}
This works great if the client and server both are running on localhost that is 127.0.0.1. But, it does not work if client and server are running on different devices. I believe that the issue is in the configuring of udp::endpoint on both sides.
The server is running on a machine which is a router by itself. The client device connects to it and thus it is P2P where only one client and one server is involved. The local inet address of the server device is 192.168.1.1. Next, the Client connects to the Server and gets assigned with the IP 192.168.1.20.
For the UDP communication, I to assigned server side udp::endpoint to 192.168.1.1 and client side udp::endpoint to 192.168.1.20. But I still don't get UDP packets. What am I missing?
If I give the endpoint set up logic in a method then this is how it is:
boost::asio::ip::udp::endpoint remote_endpoint;
boost::asio::io_service io_service;
udp::socket udp_socket{io_service};
void PrepareUDPEndpoints(bool on_server_side) {
std::string address;
if (on_server_side) {
address = "192.168.1.1";
remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(address), 13251);
udp_socket.open(boost::asio::ip::udp::v4());
} else {
address = "192.168.1.20";
udp_socket.open(boost::asio::ip::udp::v4());
remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(address), 13251);
udp_socket.bind(remote_endpoint);
}
}
I am getting the UDP packets "absolutely okay on localhost 127.0.0.1" but no packets at all when client and server running on 2 different machines. What am I doing wrong?

Winsock invalid socket error once include external sources

I am trying to create a server/client communication console, but once i include the external libraries (cryptopp) and debug, it will always terminate due socket invalid error. I have no idea what is going on.
#include <iostream>
#include <WS2tcpip.h>
#include <string>
#pragma comment (lib, "ws2_32.lib")
#include "../cryptopp565/sha.h"
using CryptoPP::SHA1;
using namespace std;
int main()
{
//initialize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Initialize winsock! program terminate." << endl;
return 1;
}
//create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! program terminate." << endl;
return 1;
}
//Promtp to get server port
string server_port_temp;
cout << "Enter port : ";
cin >> server_port_temp;
int server_port = stoi(server_port_temp);
//bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(server_port);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listening, (sockaddr*)&hint, sizeof(hint));
//tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//wait for connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
cerr << "Invalid socket ! program terminate." << endl;
return 1;
}
char host[NI_MAXHOST]; //client remote name
char service[NI_MAXHOST]; // service (poet client is connect on)
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXHOST, 0) == 0)
{
cout << host << " Connect on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " Connected on port " << ntohs(client.sin_port) << endl;
}
//close listening socket
closesocket(listening);
//while loop: communication
char buf[4096];
//communicate ________________
while (true)
{
ZeroMemory(buf, 4096);
//wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR)
{
cerr << "Error in recv(). Program terminate." << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client disconnected " << endl;
break;
}
cout << string(buf, 0, bytesReceived) << endl;
//echo message back to client
send(clientSocket, buf, bytesReceived + 1, 0);
}
//close the socket
closesocket(clientSocket);
//clean winsock
WSACleanup();
system("pause");
return 0;
}`

IPV6 Connect error 10049(A-GAIN!)

So I configured windows 8 firewall to allow IPV6 outbound and inbound connections as a precautionary measure but whenever I try to connect to either are remote host or to my own machine using the loopback address(to an ipv6 server application running simultaneously)the connect function FAILS with error 10049 regardless of what port I choose. Is this a network configuration problem? IP4 works just fine.
#include "stdafx.h"
#include <iostream>
#include <iostream>
#include <string>
#include <stdlib.h>
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <WS2tcpip.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <IPTypes.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib,"iphlpapi.lib")
using namespace std;
static int MAXPENDING = 5;
void set_interface(SOCKET s, DWORD Index);
int main(int argc,char* argv[])
{
WSADATA wsaData;
int Result;
int optv = 1;
char *optval = (char*)&optv;
int optlen = sizeof(optval);
DWORD Index = 22;
bool connected = false;
string exit = "quit";
string name;
sockaddr_in6 c_addr;
c_addr.sin6_family = AF_INET6;
char buffer[1024];
Result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (Result != NO_ERROR) {
printf("WSAStartup function failed with error: %d\n", GetLastError());
return 0;
}
SETUP:
SOCKET connector;
connector = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (connector == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
closesocket(connector);
return 1;
}
cout << "Enter host name(URL): ";
cin >> name;
cout << endl;
char *hostname = const_cast<char*>(name.c_str());
if(inet_pton(AF_INET6,hostname,&c_addr.sin6_addr)<0){
printf("InetPton() function failed with error: %d/n",GetLastError());
closesocket(connector);
return 1;
}
string p;
char *hostport;
int p0rt;
cout << "Enter the port number you wish to connect on: " ;
cin >> p;
cout << endl;
hostport = const_cast<char*>(p.c_str());
p0rt = atoi(hostport);
if(!( 0 < p0rt && p0rt < 65,536)){
cout << "Error: port number must be greater than 0 and less than 65,536. " << endl;
cout << endl;
cout << "Re-enter the port number you wish to connect on: " ;
cin >> p;
cout << endl;
hostport = const_cast<char*>(p.c_str());
p0rt = atoi(hostport);
}else{
c_addr.sin6_port = htons(p0rt);
}
if(connect(connector,(sockaddr*)&c_addr,sizeof(c_addr))<0){
printf("Connect failed with error: %d\n",GetLastError());
string cmd;
cout << endl;
cout <<"Try again? Type 'y' to reattempt connection or type any other key to exit: ";
cin >> cmd;
cout << endl;
if(cmd=="y"){
goto SETUP;
}else {
goto QUIT;
}
}else{
connected = true;
cout << "Connected to host " << hostname << " on port " << c_addr.sin6_port << endl;
cout << "Type 'quit' to exit the program " << endl;
}
while(connected==true){
int nbr = 0;
cout << endl;
cout << ">";
scanf("%s",buffer);
cout << endl;
string str(buffer);
if(str==exit){
connected = false;
goto QUIT;
}
long nbs = send(connector,buffer,sizeof(buffer),0);
if(nbs < 0){
printf("send() failed", GetLastError());
goto QUIT;
}
while(nbr < nbs){
nbr = recv(connector,buffer,sizeof(buffer),0);
if(nbr < 0){
printf("recv() failed", GetLastError());
goto QUIT;
}else if(nbr==0){
printf("recv() failed: connection closed prematurely", GetLastError());
goto QUIT;
}else if(nbr > 0){
cout << endl;
cout << ">> ";
printf(buffer);
cout << endl;
}
}
}
QUIT:
if (closesocket(connector) == SOCKET_ERROR) {
printf("closesocket function failed with error: %ld\n", GetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
};
void set_interface(SOCKET s, DWORD Index){
MIB_IF_ROW2 T2;
NET_LUID ID;
DWORD ptbuflen = (DWORD)sizeof(T2);
ConvertInterfaceIndexToLuid(Index,&ID);
T2.InterfaceLuid = ID;
GetIfEntry2(&T2);
if(WSAIoctl(s,SIO_ASSOCIATE_HANDLE,&T2,ptbuflen,NULL,0,0,NULL,NULL)>0){
printf("WSAIoctl() function failed with error: %d\n", GetLastError());
closesocket(s);
}
if(WSAIoctl(s,SIO_TRANSLATE_HANDLE,&T2,ptbuflen,NULL,0,0,NULL,NULL)>0){
printf("WSAIoctl() function failed with error: %d\n", GetLastError());
closesocket(s);
}
};
You need to zero out the portion of the sockaddr_in6 that you are not using. Zero out the enire thing first, then fill in the portions you need.
If the user fails to enter a valid port the first time, you are not validating the new port entered the second time, and you are not assigning that second port value to the sockaddr_in6 at all. You should be doing your validation in a loop, and then assign the final accepted value to the sockaddr_in6.
You are using inet_pton() when you should be using getaddrinfo() instead. inet_pton() only converts an IP address string to its binary format. It will not resolve a hostname to an IP. getaddrinfo() does that resolution instead, and it also supports converting IP address strings as well (specify the AI_NUMERICHOST flag in the hints parameter to get that behavior).

VC++ Winsock2 Error 10049. Trying to build IRC bot

I'm trying to port my IRC bot from Python to C++ and I'm running into some issues with Winsock2. I'm fairly new to sockets in C/C++ and most of this code was pieced together from various tutorials. I keep getting error 10049 and am at a loss. Any help would be appreciated greatly. Thanks!
port_ is set to 6667 and host_ is "irc.rizon.net"
WSADATA wsaData;
int starterr = WSAStartup(MAKEWORD(2,2), &wsaData);
if (starterr != 0) {
std::cout << "Error: " << WSAGetLastError() << " occurred!" << std::endl;
WSACleanup();
return 1;
}
std::cout << "WSAStartup Successful!" << std::endl;
socketfd_ = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (socketfd_ == INVALID_SOCKET) {
std::cout << "Error: " << WSAGetLastError() << " occurred!" << std::endl;
WSACleanup();
return 1;
}
std::cout << "Socket Creation Successful!" << std::endl;
sockaddr_in anews;
anews.sin_port = htons(port_);
anews.sin_addr.s_addr = inet_addr(host_.c_str());
anews.sin_family = AF_INET;
if (connect(socketfd_,(sockaddr*)&anews, sizeof(anews)) == SOCKET_ERROR) {
std::cout << "Error: " << WSAGetLastError() << " occurred!" << std::endl;
WSACleanup();
return 1;
}
std::cout << "Socket has connected successfuly!" << std::endl;
return 0;
inet_addr() takes a dotted IP address of the form "x.x.x.x" you are passing it the host name.
You can use gethostbyname():
hostent* host;
char* ip;
...
// Get the local host information
host= gethostbyname(host_.c_str());
ip= inet_ntoa(*(struct in_addr *)*host->h_addr_list);
sockaddr_in anews;
anews.sin_port = htons(port_);
anews.sin_addr.s_addr = inet_addr(ip);
anews.sin_family = AF_INET;
...
Or an easier route would be to use getaddrinfo():
struct addrinfo *ai;
if(getaddrinfo(host_.c_str(), "6667", NULL, &ai) != 0)
return 1;
socketfd_ = socket(ai->ai_family, SOCK_STREAM, 0);
if (socketfd_ == INVALID_SOCKET) {
freeaddrinfo(ai);
return 1
}
if (connect(socketfd_, ai->ai_addr, (int)ai->ai_addrlen) == SOCKET_ERROR) {
closesocket(socketfd_);
freeaddrinfo(ai);
return 1;
}
...