Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何打开具有相同本地端口的两个udp客户端套接字_C_Sockets_Udp_Udpclient_Hole Punching - Fatal编程技术网

C 如何打开具有相同本地端口的两个udp客户端套接字

C 如何打开具有相同本地端口的两个udp客户端套接字,c,sockets,udp,udpclient,hole-punching,C,Sockets,Udp,Udpclient,Hole Punching,如何像java一样使用相同的本地端口打开两个客户端套接字。 在Java中,我们可以在创建DatagramPacket时提到源端口。 我正在尝试打孔。如果我做错了什么,请纠正我 我在这里添加了我的代码 void UDPClientConnect ( string IP , string Port ) { WSADATA wsa; if ( WSAStartup(MAKEWORD(2,2),&wsa) != 0 ) { printf ( "startup failed

如何像java一样使用相同的本地端口打开两个客户端套接字。 在Java中,我们可以在创建DatagramPacket时提到源端口。 我正在尝试打孔。如果我做错了什么,请纠正我

我在这里添加了我的代码

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 ( ) ;
}

用同样的方法,我试图用同样的端口打开新的套接字

检查我在C/C++中尝试这样做的Java代码。这是不可能的

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();
}

}
import java.io.*;
导入java.net。*;
公共类UDPHolePunchingClient{
公共静态void main(字符串[]args)引发异常{
//准备插座
DatagramSocket clientSocket=新DatagramSocket();
//准备数据
byte[]sendData=“Hello”.getBytes();
//使用固定IP(X.X.X.X)将数据发送到服务器
//客户端1使用端口7070,客户端2使用端口7071
DatagramPacket sendPacket=新的DatagramPacket(sendData,
sendData.length,InetAddress.getByName(“172.24.8.110”),7070);
clientSocket.send(sendPacket);
//接收数据==>格式:“-”
DatagramPacket receivePacket=新的DatagramPacket(新字节[1024],1024);
clientSocket.receive(receivePacket);
//将响应转换为IP和端口
字符串响应=新字符串(receivePacket.getData());
String[]splitResponse=response.split(“”);
InetAddress ip=InetAddress.getByName(拆分响应[0]。子字符串(1));
int port=Integer.parseInt(splitResponse[1]);
//输出转换后的数据以供检查
System.out.println(“IP:+IP+”端口:+PORT”);
//关闭套接字并使用相同的localport打开新套接字
int localPort=clientSocket.getLocalPort();
clientSocket.close();
clientSocket=newdatagramsocket(localPort);
//设置接收数据的超时时间
clientSocket.setSoTimeout(1000);
//发送5000条消息进行测试
对于(int i=0;i<5000;i++){
//向其他客户端发送消息
sendData=(“数据包(“+i+”)).getBytes();
sendPacket=新数据包(sendData,sendData.length,ip,端口);
clientSocket.send(sendPacket);
//从其他客户端接收消息
试一试{
receivePacket.setData(新字节[1024]);
clientSocket.receive(receivePacket);
System.out.println(“REC:
+新字符串(receivePacket.getData());
}捕获(例外e){
System.out.println(“服务器超时”);
}
}
//密切联系
clientSocket.close();
}
}

与所有注释相反,您所要做的就是在
绑定()之前设置套接字选项
SO_REUSEPORT

与所有注释相反,您所要做的就是在
绑定()之前设置套接字选项
SO_REUSEPORT
与所有注释相反,您所要做的就是在
bind()

之前设置套接字选项
SO\u REUSEPORT
,与所有注释相反,您所要做的就是在
bind()
之前设置套接字选项
SO\u REUSEPORT
,看起来Java代码实际上并没有在同一端口上打开两个套接字,但是关闭第一个套接字,然后在与关闭的套接字相同的端口上打开一个新的套接字。对于未处于连接状态的UDP套接字,根本不需要这样做


如果你没有改变端口,C++代码应该能够继续使用同一个套接字,而不是新建一个套接字。假设您想镜像Java代码正在执行的操作,则不需要调用

connect
。只需使用
sendto
recvfrom
来回发送数据。

看起来Java代码实际上并不是在同一端口上打开两个套接字,而是关闭第一个套接字,然后在与关闭的套接字相同的端口上打开一个新的套接字。对于未处于连接状态的UDP套接字,根本不需要这样做


如果你没有改变端口,C++代码应该能够继续使用同一个套接字,而不是新建一个套接字。假设您想镜像Java代码正在执行的操作,则不需要调用

connect
。只需使用
sendto
recvfrom
来回发送数据。

看起来Java代码实际上并不是在同一端口上打开两个套接字,而是关闭第一个套接字,然后在与关闭的套接字相同的端口上打开一个新的套接字。对于未处于连接状态的UDP套接字,根本不需要这样做


如果你没有改变端口,C++代码应该能够继续使用同一个套接字,而不是新建一个套接字。假设您想镜像Java代码正在执行的操作,则不需要调用

connect
。只需使用
sendto
recvfrom
来回发送数据。

看起来Java代码实际上并不是在同一端口上打开两个套接字,而是关闭第一个套接字,然后在与关闭的套接字相同的端口上打开一个新的套接字。对于未处于连接状态的UDP套接字,根本不需要这样做



如果你没有改变端口,C++代码应该能够继续使用同一个套接字,而不是新建一个套接字。假设您想镜像Java代码正在执行的操作,则不需要调用

connect
。只需使用<代码> Stoto < /C>和 RevOb//Cord>来回发送数据。

C和C++都不知道“插座”是什么。哪个操作系统和编译器?在UDP中,每个端口使用一个套接字。UDP套接字可以处理任意数量的连接。在同一个本地端口上打开多个套接字在任何上下文中都没有意义。@CoffeeandCode我们可以将源端口设置为java中其他套接字的本地端口。闭包是荒谬的。问题是非常清楚的。C和C++都不知道什么是“插座”。哪个操作系统和编译器?在UDP中,每个端口使用一个套接字。UDP套接字可以处理任何数字