gpt4 book ai didi

c++ - 套接字编程,检查入口UDP缓冲区是否为空?

转载 作者:太空狗 更新时间:2023-10-29 20:46:36 25 4
gpt4 key购买 nike

我正在编写一个向服务器发送字符串的 UDP 客户端,当服务器发回多个数据包时,程序的行为并不符合我的预期。我想通过 process() 一个接一个 处理任何传入的数据包,直到入口缓冲区变空,但我认为存在与 的阻塞行为相关的问题接收.

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <winsock.h>

using namespace std;

void process(const char *in, int size)
{
fprintf(stdout, "%s\n", in);
}

int main()
{
char quack_addr[] = "127.0.0.1";
unsigned short quack_port = 9091;

WSAData data;
WSAStartup(MAKEWORD(2, 2), &data);

sockaddr_in qserver;
qserver.sin_family = AF_INET;
qserver.sin_addr.s_addr = inet_addr(quack_addr);
qserver.sin_port = htons(quack_port);
SOCKET client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

if (client <= 0)
{
fprintf(stderr, "Error - Can not create socket.\n");
exit(1);
}

while (true)
{
const int MAX = 1024;
char sbuf[MAX];
char rbuf[MAX];

fprintf(stdout, ": ");
fgets(sbuf, MAX, stdin);
int slen = strlen(sbuf);

int r = sendto(client,sbuf,slen,0,(sockaddr*)&qserver,sizeof(qserver));

// Current code:
// int rlen = recv(client, rbuf, MAX, 0);
// if (rlen > 0)
// {
// rbuf[rlen] = 0;
// process(rbuf, rlen);
// }

// Question starts here:
//
// While there is data in queue do:
// {
// (break if there is no data)
// int rlen = recv(client, rbuf, MAX, 0);
// rbuf[rlen] = 0;
// process(rbuf, rlen);
// }
}

return 0;
}

如何在调用 recv(...) 之前检查缓冲区是否为空?

这个场景出现的问题:

  1. 用户正在客户端程序中键入命令 (cmd1)。
  2. 同时,服务器向客户端发送 3 个数据包(pkt1pkt2pkt3)。
  3. 在客户端按下 Enter 后,我希望收到这 3 个数据包以及可能对应于 cmd1process() 的结果> 所有这些都一一呈现。
  4. 但是在第 3 阶段按 Enter 后,我收到了 pkt1!在向服务器发送另一个命令后,我将收到 pkt2 等等......!

我知道我的代码不足以处理这个问题,所以,我的问题是如何处理它?<​​/strong>

注意:我正在使用 netcat -L -p 9091 -u 作为 UDP 服务器

最佳答案

我认为问题(您未描述的不满意行为)来自不同的来源。让我列出一些想法和评论 c./之前所说的内容:

(1) recvfrom() 也会阻塞。但是,您想使用它。您的通信当前从环回发送和接收,这对您的玩具程序来说很好(但是:见下文)。当接收 UDP 数据时,使用 recv() 你不知道是谁发送的,因为套接字从未被 connect()ed。使用 recvfrom() 为更严肃的程序中的一些最小错误检查做好准备

(2) 由于 select() 将程序暂停到 i/o 可用性,它只会将您的套接字阻塞问题提升到一个不同的级别。但这不是问题

(3) 检查接收缓冲区是否为空,在 recvfrom() 的适当位置使用标志 MSG_PEEK。它通常只用于处理稀缺内存,但它应该可以完成这项工作。

(4) 原因 1 为什么我相信您看到了您没有更详细描述的问题:UDP 数据报保留消息边界。这意味着 recvfrom() 将读取构成任何已发送消息的整个数据 block 。但是,如果您将其读入的缓冲区小于读取的数据,则任何多余的内容都将被默默丢弃。因此,请确保您有一个大缓冲区(理想情况下为 65k)。

(5)原因2:您收到发送到环回的任何数据。如果您当前还连接到某个网络(sat,Internet),那么您捕获的内容实际上可能来自与您预期不同的来源。所以至少在休息阶段,断开连接。

阻止应该不是问题。干净编码后,您的基本逻辑是:Recvfrom() (阻塞/等待直到准备好)过程查看缓冲区是否为空是则退出如果没有,则循环返回以接收更多,

而且您目前似乎想这样做。由于您不使用多线程、优化 fie perfiormance 或类似功能,因此您不应该关心阻塞。如果您发现接收缓冲区太小,请使用

增加其大小

为 optName SO_RCVBUF 设置 sockopt()

关于c++ - 套接字编程,检查入口UDP缓冲区是否为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7784307/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com