【问题标题】:How to use both TCP and UDP in one application in c++如何在 C++ 中的一个应用程序中同时使用 TCP 和 UDP
【发布时间】:2015-02-25 02:30:34
【问题描述】:

我正在用 c++ 开发一个基于 Winsock 的服务器-客户端项目。我设计了服务器端和客户端,以便它们也可以发送和接收文本消息和文件。

然后我决定在服务器和客户端之间进行音频通信。我实际上已经实现了,但是我发现我已经使用 TCP 协议完成了所有工作,而对于音频通信,最好使用 UDP 协议。

然后我在互联网上搜索,发现可以同时使用 TCP 和 UDP。

我尝试使用 UDP 协议,但没有任何重大进展。

我的问题是我在这样的 while 循环中同时使用了 recv() 和 recvFrom():

while (true)
{
    buflen = recv(clientS, buffer, 1024, NULL);

    if (buflen > 0)
    {
        // Send the received buffer
    }
    else if (buflen == 0)
    {
        printf("closed\n");
        break;
    }

    buflen = recvfrom(udpS, buffer, 1024, NULL, (struct sockaddr*)&_s, &_size);

但是 recvFrom() 会阻塞。我认为我没有正确完成这项工作,但我不知道该怎么做。

在这里Server in C accepting UDP and TCP connections我发现了一个类似的问题,但答案只是解释,没有示例代码可以清楚地证明这一点。

现在我需要你帮我弄清楚如何从 TCP 和 UPD 连接中接收数据。

感谢任何帮助。

【问题讨论】:

  • 使用selectpoll 或类似的东西,如epoll 或kqueue(尽管同时使用TCP 和UDP 通常不是一个好主意,因为TCP 会导致丢包)。
  • 查看selectpoll
  • 我实际上需要一个简单的示例代码。我研究了 select() 但结果是纯粹的解释。
  • OP使用的是WinSock,即Windows,没有poll()epoll(),只有select(),还有非标准的WSAAsyncEvent()WSAAsyncSelect()扩展。
  • @Remy:还有WSAPoll。您可能指的是 WSAEventSelect,而不是 WSAAsyncEvent。

标签: c++ sockets networking tcp udp


【解决方案1】:

一次处理多个socket时,使用select()在读取前知道哪个socket有数据挂起,例如:

while (true)
{
    fd_set rfd;
    FD_ZERO(&rfd);
    FD_SET(clientS, &rfd);
    FD_SET(udpS, &rfd);

    struct timeval timeout;
    timeout.tv_sec = ...;
    timeout.tv_usec = ...;

    int ret = select(0, &rfd, NULL, NULL, &timeout);
    if (ret == SOCKET_ERROR)
    {
         // handle error
         break;
    }

    if (ret == 0)
    {
         // handle timeout
         continue;
    }

    // at least one socket is readable, figure out which one(s)...

    if (FD_ISSET(clientS, &rfd))
    {
        buflen = recv(clientS, buffer, 1024, NULL);
        if (buflen == SOCKET_ERROR)
        {
            // handle error...
            printf("error\n");
        }
        else if (buflen == 0)
        {
            // handle disconnect...
            printf("closed\n");
        }
        else
        {
            // handle received data...
        }
    }

    if (FD_ISSET(udpS, &rfd))
    {
        buflen = recvfrom(udpS, buffer, 1024, NULL, (struct sockaddr*)&_s, &_size);
        //...
    }
}

【讨论】:

  • 谢谢。我会使用你的示例代码,如果它有效,我会接受你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 2015-12-13
  • 2017-04-04
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多