0

How to open two client socket with the same local port like java. In Java we can mention the source port while creating DatagramPacket. I am trying to do UDP hole punching. Correct me if i done anything wrong.

I have added my code here.

void UDPClientConnect ( string IP , string Port ) 
{ 
    WSADATA wsa;


if ( WSAStartup(MAKEWORD(2,2),&wsa) != 0 )
{
    printf ( "startup failed %d\n" , WSAGetLastError() ) ;
    return ;
}
int reuse = 1 ; 
SOCKET s = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,(char*) &reuse, sizeof(int)); 

struct sockaddr_in si_other;
int slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];

int p = atoi ( Port.c_str() ) ;

memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;

si_other.sin_port = htons(p);
si_other.sin_addr.S_un.S_addr = inet_addr( IP.c_str() );

strcpy_s ( message , "Hello" ) ;


//send the message
if ( sendto ( s , message , strlen(message) , 0 , (struct sockaddr *) &si_other , slen ) == SOCKET_ERROR)
{
    printf ( "sendto() failed with error code : %d" , WSAGetLastError() ) ;
   return ;
}

//receive a reply and print it
memset ( buf , '\0' , BUFLEN ) ;
//try to receive some data, this is a blocking call
if ( recvfrom ( s , buf , BUFLEN , 0 , (struct sockaddr *) &si_other , &slen ) == SOCKET_ERROR )
{
    printf("recvfrom() failed with error code : %d" , WSAGetLastError());
    return ;
}

struct sockaddr_in localAddress;
int addrlen = sizeof(localAddress) ;

getsockname ( s , (struct sockaddr*)&localAddress , &addrlen ) ;

USHORT LocalPort = localAddress.sin_port ;
IN_ADDR localAddr = localAddress.sin_addr ;

printf("local address: %s\n", inet_ntoa( localAddress.sin_addr));
printf("local port: %d\n", (int) ntohs(localAddress.sin_port));

printf ( "\n******************************************\n\n" ) ;

int pos = 1 ;
CStringA CBuff = CStringA ( buf ) ;

string RemortPort = CBuff.Tokenize ( "-" , pos ) ;
string RemortIp = CBuff.Tokenize ( "-" , pos ) ;


reuse = 1 ;

SOCKET Sock_Reuse = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;

setsockopt( Sock_Reuse , SOL_SOCKET, SO_REUSEADDR,(char*) &reuse, sizeof(int)); // optional, but recommended

struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(LocalPort);
sin.sin_addr.s_addr=INADDR_ANY;

if ( SOCKET_ERROR == connect(Sock_Reuse,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)))
{
    printf ( "bind failed %d" , WSAGetLastError() ) ;
}

closesocket ( Sock_Reuse ) ;
closesocket ( s ) ;
WSACleanup ( ) ;

}

In the same method I am trying to open the new socket with same port.

Check this Java Code I am trying to do like this in C/C++. It is not Possible ??

import java.io.* ;
import java.net.* ;

public class UDPHolePunchingClient {

public static void main(String[] args) throws Exception {
    // prepare Socket
    DatagramSocket clientSocket = new DatagramSocket();

    // prepare Data
    byte[] sendData = "Hello".getBytes();

    // send Data to Server with fix IP (X.X.X.X)
    // Client1 uses port 7070, Client2 uses port 7071
    DatagramPacket sendPacket = new DatagramPacket(sendData,
            sendData.length, InetAddress.getByName("172.24.8.110"), 7070);
    clientSocket.send(sendPacket);

    // receive Data ==> Format:"<IP of other Client>-<Port of other Client>"
    DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
    clientSocket.receive(receivePacket);

    // Convert Response to IP and Port
    String response = new String(receivePacket.getData());
    String[] splitResponse = response.split("-");
    InetAddress ip = InetAddress.getByName(splitResponse[0].substring(1));

    int port = Integer.parseInt(splitResponse[1]);

    // output converted Data for check
    System.out.println("IP: " + ip + " PORT: " + port);

    // close socket and open new socket with SAME localport
    int localPort = clientSocket.getLocalPort();
    clientSocket.close();
    clientSocket = new DatagramSocket(localPort);

    // set Timeout for receiving Data
    clientSocket.setSoTimeout(1000);

    // send 5000 Messages for testing
    for (int i = 0; i < 5000; i++) {

        // send Message to other client
        sendData = ("Datapacket(" + i + ")").getBytes();
        sendPacket = new DatagramPacket(sendData, sendData.length, ip, port);
        clientSocket.send(sendPacket);

        // receive Message from other client
        try {
            receivePacket.setData(new byte[1024]);
            clientSocket.receive(receivePacket);
            System.out.println("REC: "
                    + new String(receivePacket.getData()));

        } catch (Exception e) {
            System.out.println("SERVER TIMED OUT");
        }
    }

    // close connection
    clientSocket.close();
}

}
6
  • C and C++ both have no idea what a "socket" is. Which operating system and compiler? Commented Jul 30, 2015 at 8:10
  • In UDP, you use a single socket per port. A UDP socket can handle any number of connections. Commented Jul 30, 2015 at 8:21
  • Opening multiple sockets on the same local port wouldn't make sense in any context. Commented Jul 30, 2015 at 8:23
  • @CoffeeandCode We can set the source port as local port port of some other socket in java. Commented Jul 30, 2015 at 9:04
  • 2
    The closure is ridiculous. The question is perfectly clear. Commented Jul 30, 2015 at 9:36

2 Answers 2

3

Contrary to all the commentary, all you have to do is set the socket option SO_REUSEPORT prior to the bind().

Sign up to request clarification or add additional context in comments.

14 Comments

I have done this. but where i can set the local port of current socket.
Err, in the bind() call?
If I use bind call windows throwing some alert.
@bala That tells jus precisely nothing. What alert? Vague statements like that are not acceptable. In any case, if you don't use the bind() call you can't use any specific port, let alone re-use it.
The main problem with opening two or more UDP sockets on the same port is that when a packet comes in, it is undefined which socket will receive the packet. It could be just one (any one), or it could be all. This is assuming unicast. If on the other hand the sockets are listening for multicast traffic, incoming multicast packets will be delivered to any socket that has joined the multicast group for that packet.
|
0

It seems the Java code is not in fact opening two sockets on the same port, but closing the first socket then opening a new one on the same port as the one that was closed. For a UDP socket not in a connected state, that shouldn't be necessary at all.

If you're not changing the port, your C++ code should be able to continue to use the same socket instead of making a new one. Assuming you want to mirror what the Java code is doing, you shouldn't need to call connect. Just use sendto and recvfrom to send data back and forth.

1 Comment

It's not even necessary in the connected state. Just connect it to null: that's a disconnect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.