C ++套接字选项重用端口

时间:2011-04-12 12:22:16

标签: c++ sockets multicast

我的c ++套接字有问题 我正在使用MFC中的CAsyncSocket,我想加入多播组 此外,我需要在这个小组上有多个听众,这里是我遇到麻烦的地方 我在网上找到了一些例子,但似乎没有用。
这是我的代码:

//create socket on port 17233   
BOOL bRet = Create(17233,SOCK_DGRAM, FD_READ);

//set reuse socket option  
BOOL bMultipleApps = TRUE;
bRet = SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);

//join multicast group
ip_mreq m_mrMReq;           // Contains IP and interface of the host group
m_mrMReq.imr_multiaddr.s_addr = inet_addr((LPCSTR)"224.30.0.1");    /* group addr */ 
m_mrMReq.imr_interface.s_addr = htons(INADDR_ANY);      /* use default */

int uRes =setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR *)&m_mrMReq, sizeof(m_mrMReq));

运行时没有错误。
但是当我尝试运行该应用程序的另一个实例时,它无法在该端口上创建新的套接字,因为该端口正在使用中。

我在C#中做到了这一点并且工作得很好:

IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
s.Bind(ipep);
IPAddress ip = IPAddress.Parse(mcastGroup);
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
s.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.MulticastTimeToLive, int.Parse("1"));

因此,如果任何机构发现我的代码存在问题或有一些提示,我将很乐意欣赏。

编辑1:
CAsyncSocket是TCP套接字吗?

编辑2: 阅读Can two applications listen to the same port?后 我觉得我很困惑。我需要一个多播UDP端口,可以使用SO_REUSEADDR

访问多个应用程序

编辑澄清:

BOOL bRet = Create(17233,SOCK_DGRAM, FD_READ)

创建UDP套接字并将其绑定到端口17223 要使SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);工作,你需要在绑定之前设置它,因为@Hasturkun说 最终的工作代码如下所示:

    BOOL bRet = Socket(SOCK_DGRAM, FD_READ);
    if(bRet != TRUE)
    {
        UINT uErr = GetLastError();
        std::cout<<"Error:"<<uErr<<std::endl;
        return FALSE;
    }else{
        std::cout<<"Create sock: OK"<<std::endl;
    }

    //add reuse
    BOOL bMultipleApps = TRUE;      /* allow reuse of local port if needed */
    SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);

    //bind
    bRet = Bind(17233, NULL);
    if(bRet != TRUE)
    {
        UINT uErr = GetLastError();
        std::cout<<"Error(BIND):"<<uErr<<std::endl;
    }else{
        std::cout<<"BIND sock: OK"<<std::endl;
    }

谢谢,
加布里埃尔

3 个答案:

答案 0 :(得分:1)

我想这是因为您将客户端套接字绑定到特定端口和地址。也许在它的构造函数上:

BOOL bRet = Create(17233,SOCK_DGRAM, FD_READ);

您不应将客户端套接字绑定到地址。让windows为您管理。您应该可以选择不创建通过特定端口的套接字,或者如果不这样做,则应该使用另一个端口创建套接字。

此外,BOOL bMultipleApps = TRUE;选项不会像您认为的那样工作。它在套接字中设置了一个逗留选项,但是一旦创建和监听,套接字(我的意思是套接字端口)就无法在其他应用程序中使用,无论你做什么。

检查出来:so-linger-and-closing-socketswinsock

修改

我也不知道你的c#代码中port的值:

IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);

您确定每次运行应用时port都没有获得不同的值吗?

正如我所说,尝试在不同的端口创建套接字以查看发生的情况。 Google so_linger知道这意味着什么。

编辑2:

看看:Can two application listen to the same port?

编辑3:

也许你的c#代码:

IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);

将地址绑定到其他NIC。你在同一台电脑上有2个nic吗?如果这样做,您可以在两个端口绑定相同的端口。

编辑4:

使用UDP套接字的示例:Sending & Receiving UDP Datagrams with MFC's CAsyncSocket

答案 1 :(得分:1)

如果boost是您的选项,请考虑使用Asio。它非常简单,this示例显示了一个简单的多播接收器。

多个听众的重要部分是:

socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));

如果你不清楚你的应用程序在做什么,只需运行netstat,你会看到例如套接字及其绑定方式(IP,端口和协议):

netstat -an

...并查找您感兴趣的端口。如果您运行多个应用程序侦听同一端口,您应该会看到同一端口的多个条目,其中UDP作为协议。

答案 2 :(得分:1)

您应该能够将套接字的创建与绑定分开,使用Socket创建套接字,例如。

BOOL bRet = Socket(SOCK_DGRAM, FD_READ);

然后在设置sockopt

后将其与Bind绑定
BOOL bMultipleApps = TRUE;
bRet = SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);

bRet = Bind(17233, NULL);