读写选择使用相同插槽(TCP) [英] read and write to same socket (TCP) using select

查看:125
本文介绍了读写选择使用相同插槽(TCP)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在编写一个客户端和服务器做(我认为是)pretty简单的网络通信。多张客户端连接到其中,然后应该将数据发送回所有其他客户端的服务器

We're writing a client and a server to do (what I thought was) pretty simple network communications. Mulitple clients connect to the server which then is supposed to send the data back to all other clients.

服务器只是坐在阻塞选择循环,等待交通,当它来临的时候,将数据发送给其他客户端。这似乎工作得很好。

The server just sits in a blocking select loop waiting for traffic, and when it comes, sends the data to the other clients. This seems to work just fine.

问题是客户端。为了响应读,它有时会希望做一个写操作。

The problem is the client. In response to a read, it will sometimes want to do a write.

不过,我发现,如果我使用:

However, I've found that if I use:

 rv = select(fdmax + 1, &master_list, NULL, NULL, NULL);

我的code将阻塞,直到有新的读取数据。但有时(异步,从另一个线程)我将有新的数据网络通信线程上写字。所以,我想我的选择周期性地唤醒,让我检查是否有数据来写,如:

My code will block until there is new data to read. But sometimes (asynchronously, from another thread) I'll have new data to write on the network communication thread. So, I want my select to wake up periodically and let me check if there are data to write, like:

if (select(....) != -1)
{
  if (FD_SET(sockfd, &master_list))
     // handle data or disconnect
  else
     // look for data to write and write() / send() those.
}

我试过设置选择轮询与模式(或可笑短超时):

I tried setting the select to poll mode (or ridiculously short timeouts) with:

// master list contains the sockfd from the getaddrinfo/socket/connect seq
struct timeval t;
memset(&t, 0, sizeof t);
rv = select(fdmax + 1, &master_list, NULL, NULL, &t);

但已经发现,然后再客户从来没有得到任何输入的数据。

but have found that then then client never gets any incoming data.

我也尝试设置套接字fd是非阻塞的,如:

I also tried setting the socket fd to be non-blocking, like:

fcntl(sockfd, F_SETFL, O_NONBLOCK);

但是,这并不解决问题:

but that doesn't solve the problem:


  1. 如果我的客户端选择()没有 timeval结构,读取数据的作品,但它永远不会放开让我找可写数据。

  2. 如果我的客户端选择()有一个的timeval 来得到它的轮询,那么它从来没有信号,有是传入的数据读取,以及我的应用程序冻结想着有没有做网络连接(尽管事实上,所有其他函数调用成功)

  1. if my client select() has no struct timeval, reading data works, but it never unblocks to let me look for writable data.
  2. if my client select() has a timeval to get it to poll, then it never signals that there are incoming data to read, and my app freezes thinking there is no network connection made (despite the fact that all other function calls have succeeded)

任何指针都以什么我可以做错了什么?它是不可能做同一插座上读写(我不能相信这是真的)。

Any pointers at all as to what I could be doing wrong? Is it not possible to do read-write on the same socket (I can't believe that to be true).

(编辑:正确答案,而我在服务器上而不是在客户端上记住的东西,是有第二次的fd_set,然后复制master_list每次调用之前选择()

( The correct answer, and thing that I remembered on the server but not on the client, is to have a second fd_set, and copy master_list before each call to select():

// declare and FD_ZERO read_fds:
// put sockfd in master_list

while (1)
{
   read_fds = master_list;
   select(...);

   if (FD_ISSET(read_fds))
     ....
   else
     // sleep or otherwise don't hog cpu resources
}

推荐答案

一切看起来很好,除了行,你做的如果(FD_SET(的sockfd,&安培; master_list))。我有一个非常类似code结构,我用 FD_ISSET 。你应该测试是否列表设置,不要再设置它。除此之外,我看没有别的。

Everything looks fine, except the line where you do if (FD_SET(sockfd, &master_list)). I have a very similar code structure and I used FD_ISSET. You're supposed to test if the list is set, not to set it again. Other than that, I see nothing else.

编辑。另外,我对超时以下内容:

Edit. Also, I have the following for the timeout:

timeval listening_timeout;
listening_timeout.tv_sec = timeout_in_seconds;
listening_timeout.tv_usec = 0;

也许有一个问题,如果你把它设置为0(因为你似乎是在做什么?)

perhaps there's an issue if you set it to 0 (as you seem to be doing?)

EDIT2。我记得我遇到了一个奇怪的问题,当我不清除读取后选择EXITED设置,我再次进入之前。我不得不做这样的事情:

Edit2. I remembered I ran into a strange problem when I wasn't clearing the read set after the select exited and before I entered it again. I had to do something like:

FD_ZERO(&sockfd);
FD_SET(sockfd, &rd);

我在进入之前选择。我不记得为什么虽然。

before I was entering select. I can't remember why though.

这篇关于读写选择使用相同插槽(TCP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆