如何在单个服务器中组合TCP和UDP?

时间:2013-04-21 23:04:24

标签: c linux sockets udp tcpserver

我对套接字编程完全不熟悉,我想在C中编写一个组合的TCP / UDP-Server套接字,但我不知道如何将这两者结合起来。

所以目前,我确实知道TCP和UDP-Server / -Clients如何工作,我已经为TCP和UDP编写了客户端。我也知道我必须以某种方式使用select() - 函数,但我不知道该怎么做。

我必须读取两个数字,这些数字通过TCP或UDP客户端发送到TCP- / UDP-Server,然后使用这些数字进行一些计算,然后将结果打印在服务器上。

是否有人知道该教程或示例代码或可以帮助我?

或者至少是select()函数的一个很好的解释。

4 个答案:

答案 0 :(得分:4)

基本上,使用事件循环。它的工作原理如下:

  1. 我现在有什么需要做的吗?如果是这样,那就去做吧。

  2. 计算我下次需要做多久的事情。

  3. 调用select指定我愿意在读取集中读取的所有套接字以及我在写集中尝试写入的所有套接字。

  4. 如果我们发现任何可以阅读的套接字,请从中读取。

  5. 如果我们发现任何可以写入的套接字,请尝试写入它们。如果我们编写了我们需要编写的所有内容,请将其从写集中删除。

  6. 转到第1步。

  7. 通常,要写入套接字,请遵循以下逻辑:

    1. 我是否已经尝试写入此套接字?如果是这样,只需将其添加到队列中即可完成。

    2. 尝试将数据写入套接字。如果我们发送了所有内容,我们就完成了。

    3. 将剩余部分保存在队列中,并将此套接字添加到我们的写入集中。

    4. 要记住三件事:

      1. 您必须将所有套接字设置为非阻塞。

      2. 请务必先复制文件描述符集,然后再将其传递给select,因为select会对其进行修改。

      3. 对于TCP连接,您可能需要自己的写入队列。

答案 1 :(得分:0)

我们的想法是在服务器内部混合使用TCP部分和UDP部分。

然后您复用输入。您可以使用旧的select(2)多路复用呼叫,但它有一些限制(谷歌用于C10K problem)。使用poll(2) 多路呼叫更可取。

您可能希望使用一些事件循环库,例如libev(使用selectpoll或某些更高级的机制,如epoll)。 BTW,图形工具包(例如GTK或Qt)也提供了他们自己的偶数循环机制。

阅读一些好的Linux编程书,如Advanced Linux Programming 本书(可在线获取),其中有关于多路复用系统调用和事件循环的章节。这些太复杂了,在这样的答案中几分钟内无法解释。书籍更好地解释了它们。

答案 2 :(得分:0)

1)简单地写一个tcp / udp服务器代码,当收到消息时,只需将其打印出来。

2)将打印代码替换为process_message()函数。

然后,您已成功将TCP和UDP服务器组合到相同的过程中。

小心你的处理程序,它应该应对parellel执行。

答案 3 :(得分:0)

您可以尝试此stream_route_handler,它是c / c ++应用程序,您可以在单个c / c ++应用程序中添加tcp / udp处理程序。这已被用于交通繁忙的路线,并用于记录服务目的。

使用示例

void read_data(srh_request_t *req);
void read_data(srh_request_t *req) {
  char *a = "CAUSE ERROR FREE INVALID";

  if (strncmp( (char*)req->in_buff->start, "ERROR", 5) == 0) {
    free(a);
  }
  // printf("%d,  %.*s\n", i++, (int) (req->in_buff->end - req->in_buff->start), req->in_buff->start);
  srh_write_output_buffer_l(req, req->in_buff->start, (req->in_buff->end - req->in_buff->start));
  // printf("%d,  %.*s\n", i++, (int) (req->out_buff->end - req->out_buff->start),   req->out_buff->start);
} 

int main(void) {

  srh_instance_t * instance = srh_create_routing_instance(24, NULL, NULL);
  srh_add_udp_fd(instance, 12345, read_data, 1024);
  srh_add_tcp_fd(instance, 3232, read_data, 64);

  srh_start(instance);

  return 0;
}

如果您使用的是C ++程序,则可能需要此示例代码。 stream route with spdlog