18
votes

I want to create a Winsock UDP socket that only sends data to a client. I want the kernel to choose an available port for me. On the other hand, I want to indicate which local IP to use, since I'm running a few nics.

I've tried combing through the maze of socket options, as well as binding with the port in the socket address set to 0 to no avail.

My code is in Win32 C++.

4

4 Answers

25
votes

Please excuse the lack of error checking:

char pkt[...];
size_t pkt_length = ...;
sockaddr_in dest;
sockaddr_in local;
WSAData data;
WSAStartup( MAKEWORD( 2, 2 ), &data );

local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr( <source IP address> );
local.sin_port = 0; // choose any

dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr( <destination IP address> );
dest.sin_port = htons( <destination port number> );

// create the socket
SOCKET s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
// bind to the local address
bind( s, (sockaddr *)&local, sizeof(local) );
// send the pkt
int ret = sendto( s, pkt, pkt_length, 0, (sockaddr *)&dest, sizeof(dest) );
11
votes

The answer of Graeme Perrow doesn't work anymore because inet_addr is deprecated. Use inet_pton instead like this:

#include <string>
#include <WinSock2.h>
#include <Ws2tcpip.h>

#pragma comment(lib, "ws2_32.lib")
using namespace std;

int main() {
    const char* pkt = "Message to be sent";
    const char* srcIP = < source IP address >;
    const char* destIP = < destination IP address >;
    sockaddr_in dest;
    sockaddr_in local;
    WSAData data;
    WSAStartup(MAKEWORD(2, 2), &data);

    local.sin_family = AF_INET;
    inet_pton(AF_INET, srcIP, &local.sin_addr.s_addr);
    local.sin_port = htons(0);

    dest.sin_family = AF_INET;
    inet_pton(AF_INET, destIP, &dest.sin_addr.s_addr);
    dest.sin_port = htons(< destination port number >);

    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    bind(s, (sockaddr *)&local, sizeof(local));

    sendto(s, pkt, strlen(pkt), 0, (sockaddr *)&dest, sizeof(dest));

    closesocket(s);
    WSACleanup();

    return 0;
}
-1
votes

Not a direct "HowTo", but I have been using an open source library called "ACE (Adaptive Communication Environment" for all my TCP and UDP socket programming and found it very useful and powerful. It takes a "software pattens" approach to providing building blocks to solve your particular problem. I was able to use their UDP encapsulation to connect to a given port and have replies sent to a free port chosen by the system. Alternatively you can specify the return port if you wish. ACE is available here: ACE Homepage

-1
votes

When you say "I want to indicate which local IP to use, since I'm running a few nics", do you mean that you want to specify the ip address, or do you want to specify the nic and use the associated ip address?

If you are trying to specify the nic, this question should be relevant.