Jump to content

Simplest cross-platform way to send packets?


Josh
 Share

Recommended Posts

I've done some reading and I think I understand the NAT punch-through problem now and I am preparing to solve it.

I'm looking for the simplest way possible to send a bunch of UDP packets to a specific IP address.  The packets don't need any format and will never even be read, I just need to spam an IP address with a bunch of nonsense data.

What's the simplest cross-platform method to do this?

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • 2 weeks later...

Here's a rough first pass at a Socket class for doing exactly this:

#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <iostream>

#ifdef LEADWERKS_5
class Socket : public SharedObject
#else
class Socket : public Object
#endif
{
	Socket();
	virtual ~Socket();
	
	std::string ip;
	int port;
	int sock;
	
#ifndef LEADWERKS_5
	static Socket* Create(const std::string ip, const int port);
#endif	
	static int resolvehelper(const char* hostname, int family, const char* service, sockaddr_storage* pAddr);
};
#ifdef LEADWERKS_5
extern shared_ptr<Socket> CreateSocket(const std::string ip, const int port);
#endif

Socket::Socket() : sockaddr_storage addrDest ({}), port (0), sock(0) {}

Socket::~Socket()
{
	if (sock!=0) closesocket(sock);
	sock = 0;
}

int Socket::resolvehelper(const char* hostname, int family, const char* service, sockaddr_storage* pAddr)
{
    int result;
    addrinfo* result_list = NULL;
    addrinfo hints = {};
    hints.ai_family = family;
    hints.ai_socktype = SOCK_DGRAM; // without this flag, getaddrinfo will return 3x the number of addresses (one for each socket type).
    result = getaddrinfo(hostname, service, &hints, &result_list);
    if (result == 0)
    {
        //ASSERT(result_list->ai_addrlen <= sizeof(sockaddr_in));
        memcpy(pAddr, result_list->ai_addr, result_list->ai_addrlen);
        freeaddrinfo(result_list);
    }

    return result;
}

#ifdef LEADWERKS_5
shared_ptr<Socket> CreateSocket(const std::string& ip, const int port) {
	auto socket = make_shared<Socket>();
#else
Socket* Socket::Create(const std::string& ip, const int port) {
	auto socket = new Socket;	
#endif
    socket->sock = socket(AF_INET, SOCK_DGRAM, 0);
	
    sockaddr_in addrListen = {}; // zero-int, sin_port is 0, which picks a random port for bind.
    addrListen.sin_family = AF_INET;
    int result = bind(socket->sock, (sockaddr*)&addrListen, sizeof(addrListen));
    if (result == -1)
    {
       int lasterror = errno;
       std::cout << "error: " << lasterror;
       exit(1);
    }
    
    result = resolvehelper( ip, AF_INET, std::string(port), &socket->addrDest);
    if (result != 0)
    {
       int lasterror = errno;
       Print("Error: " + std::string(lasterror));
       return nullptr;
    }	
	
	return socket;
}

#ifdef LEADWERKS_5
bool Socket::Send(shared_ptr<Bank> data)
#else
bool Socket::Send(const Bank* data)
#endif
{
	Send(bank->buf,bank->GetSize());
}

bool Socket::Send(const void* data, const int size)
{
    return size == sendto(sock, data, size, 0, (sockaddr*)&addrDest, sizeof(addrDest));
}

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Alright, my socket class works now and I can spam random packets at any webhost or IP address:

#include "../Leadwerks.h"

namespace Leadwerks
{
	//http://www.binarytides.com/code-a-simple-socket-client-class-in-c/

	const int SOCKET_UDP = SOCK_DGRAM;
	const int SOCKET_TCP = SOCK_STREAM;

	bool Socket::Initialized = false;

	Socket::Socket() : port(0), sock(0) {}

	Socket::~Socket()
	{
#ifdef _WIN32
		if (sock != 0) closesocket(sock);
#else
		if (sock != 0) close(sock);
#endif
		sock = 0;
	}

#ifdef LEADWERKS_5
	shared_ptr<Socket> CreateSocket(const std::string ip, const int port, const int protocol)
#else
	Socket* Socket::Create(const std::string address, const int port, const int protocol)
#endif
	{
#ifdef _WIN32
		if (!Initialized)
		{
			WORD wVersionRequested;
			WSADATA wsaData;
			int err;
			wVersionRequested = MAKEWORD(2, 2);
			err = WSAStartup(wVersionRequested, &wsaData);
			if (err == 0)
			{
				Initialized = true;
			}
			else
			{
				return nullptr;
			}
		}
#endif
#ifdef LEADWERKS_5
		auto socket = make_shared<Socket>();
#else
		auto socket_ = new Socket;
#endif
		socket_->sock = socket(AF_INET, protocol, 0);
		socket_->address = address;
		socket_->port = port;
		
		if (inet_addr(address.c_str()) == -1)
		{
			struct hostent *he;
			struct in_addr **addr_list;

			//resolve the hostname, its not an ip address
			he = gethostbyname(address.c_str());
			if (he == NULL)
			{
				//gethostbyname failed
				//herror("gethostbyname");
				//cout << "Failed to resolve hostname\n";
#ifndef LEADWERKS_5
				socket_->Release();
#endif
				return nullptr;
			}

			//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
			addr_list = (struct in_addr **) he->h_addr_list;
			for (int i = 0; addr_list[i] != NULL; i++)
			{
				//strcpy(ip , inet_ntoa(*addr_list[i]) );
				socket_->server.sin_addr = *addr_list[i];
				//cout << address << " resolved to " << inet_ntoa(*addr_list[i]) << endl;
				break;
			}
		}
		else
		{
			socket_->server.sin_addr.s_addr = inet_addr(address.c_str());
		}

		socket_->server.sin_family = AF_INET;
		socket_->server.sin_port = htons(port);

		//Connect to remote server
		if (connect(socket_->sock, (struct sockaddr *)&socket_->server, sizeof(server)) < 0)
		{
#ifndef LEADWERKS_5
			socket_->Release();
#endif
			return nullptr;
		}
		return socket_;
	}

#ifdef LEADWERKS_5
	bool Socket::Send(shared_ptr<Bank> data)
#else
	bool Socket::Send(Bank* data)
#endif
	{
		return Send(data->buf, data->GetSize());
	}

#ifdef LEADWERKS_5
	int Socket::Receive(shared_ptr<Bank> data)
#else
	int Socket::Receive(Bank* data)
#endif
	{
		return Receive(data->buf, data->GetSize());
	}

	bool Socket::Send(const void* data, const int size)
	{
		return send(sock, (const char*)data, size, 0) == size;
	}

	int Socket::Receive(void* data, const int size)
	{
		return recv(sock, (char*)data, size, 0);
	}
}

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...