Tag: 选择

在套接字关闭时取消阻止recvfrom

假设我开始在端口上接收线程。 套接字调用将阻止recvfrom。 然后,不知何故在另一个线程中,我关闭套接字。 在Windows上,这将取消阻止recvfrom,我的线程执行将终止。 在Linux上,这不会解锁recvfrom,因此,我的线程永远不会做任何事情,并且线程执行不会终止。 任何人都可以帮助我解决Linux上发生的事情吗? 当套接字关闭时,我希望recvfrom解除阻塞 我一直在阅读有关使用select()的内容,但我不知道如何将它用于我的特定情况。

使用select读取和写入相同的套接字(TCP)

我们正在写一个客户端和服务器(我认为是)非常简单的网络通信。 多个客户端连接到服务器,然后服务器将数据发送回所有其他客户端。 服务器只是位于阻塞select循环中等待流量,当它到来时,将数据发送到其他客户端。 这似乎工作得很好。 问题是客户。 在阅读时,它有时会想要写一次。 但是,我发现如果我使用: rv = select(fdmax + 1, &master_list, NULL, NULL, NULL); 我的代码将阻塞,直到有新数据要读取。 但有时(异步,来自另一个线程)我将在网络通信线程上写入新数据。 所以,我希望我的select定期唤醒,让我检查是否有要写的数据,如: if (select(….) != -1) { if (FD_SET(sockfd, &master_list)) // handle data or disconnect else // look for data to write and write() / send() those. } 我尝试将选择设置为轮询模式(或荒谬的短暂超时): // master list contains the sockfd from the getaddrinfo/socket/connect […]

有没有办法检测远程对等端已关闭TCP套接字,而不读取它?

首先,一些背景来解释动机:我正在研究一个非常简单的基于select()的TCP“镜像代理”,它允许两个防火墙的客户端间接地相互通信。 两个客户端都连接到此服务器,并且只要两个客户端都连接,客户端A发送到服务器的任何TCP字节都将转发到客户端B,反之亦然。 这或多或少有效,只有一个小问题:如果客户端A连接到服务器并在客户端B连接之前开始发送数据,则服务器没有任何地方可以放置数据。 我不想在RAM中缓冲它,因为这可能最终使用大量的RAM; 我也不想丢弃数据,因为客户端B可能需要它。 所以我选择了第三个选项,即在客户端B连接之前,不要在客户端A的套接字上选择() – for-read-ready。 这样客户端A就会阻塞,直到一切都准备就绪。 这或多或少也有效,但是在客户端A的套接字上没有选择准备就绪的副作用是,如果客户端A决定关闭他与服务器的TCP连接,则服务器不会收到有关该事实的通知 – – 至少,直到客户端B出现并且服务器最终在客户端A的套接字上选择for-ready-ready,读取任何未决数据,然后获得套接字关闭通知(即recv()返回0)。 如果服务器有一些方法知道(及时)客户端A关闭他的TCP连接,我更喜欢它。 有没有办法知道这个? 在这种情况下轮询是可以接受的(例如,我可以让select()每分钟唤醒一次并在所有套接字上调用IsSocketStillConnected(sock),如果存在这样的函数)。

使用select()进行非阻塞套接字连接始终返回1

这个问题非常相似(或几乎完全相同) 在非阻塞套接字连接中,select()总是返回1 ; 但是,我似乎无法找到我的代码蹒跚的地方。 我正在使用非阻塞套接字,并希望在将客户端连接到服务器时使用select()来检查超时/成功。 问题是select()总是几乎立即返回1,即使我甚至没有服务器运行,也没有什么可以连接到。 在此先感谢您的帮助,代码段如下: //Loop through the addrinfo structs and try to connect to the first one we can for(p = serverinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { //We couldn’t create the socket, try again perror(“client: socket”); continue; } //Set the socket […]

使用select()表示非阻塞套接字

我正在尝试使用select函数在服务器和1个客户端(不再)之间进行非阻塞i / o,其中通信流畅(可以随时发送而另一个将在不等待发送的情况下接收)。 我找到了一些包含一些代码的教程,并尝试将其改编为我的。 这就是我所拥有的 – 服务器 #define PORT “4950” #define STDIN 0 struct sockaddr name; void set_nonblock(int socket) { int flags; flags = fcntl(socket,F_GETFL,0); assert(flags != -1); fcntl(socket, F_SETFL, flags | O_NONBLOCK); } // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) return &(((struct sockaddr_in*)sa)->sin_addr); return &(((struct sockaddr_in6*)sa)->sin6_addr); […]

如何通知select()立即返回?

我有一个工作线程正在侦听TCP套接字以获取传入流量,并缓冲接收到的主线程要访问的数据(让我们称之为套接字A )。 但是,工作线程也必须做一些常规操作(比如每秒一次),即使没有数据进入。因此,我使用select()超时,这样我就不需要继续轮询。 (注意,在非阻塞套接字上调用receive()然后hibernate一秒钟并不好:即使主线程可能无法立即处理它,主线程也应立即可用传入数据。因此需要缓冲。) 现在,我还需要能够发信号通知工作线程立即执行其他操作; 从主线程,我需要让工作线程的select()返回。 现在,我已经解决了这个问题(从这里和这里基本采用的方法): 在程序启动时,工作线程为此创建了一个数据报(UDP)类型的附加套接字,并将其绑定到某个随机端口(让我们称之为套接字B )。 同样,主线程创建一个数据报套接字用于发送。 在调用select() ,工作线程现在在fd_set列出A和B. 当主线程需要发出信号时,它会将几个字节发送到sendto()几个字节到localhost上的相应端口。 回到工作线程中,如果在select()返回后B保留在fd_set ,则调用recvfrom()并忽略接收的字节。 这似乎工作得很好,但我不能说我喜欢这个解决方案,主要是因为它需要为B绑定一个额外的端口,还因为它增加了几个额外的套接字API调用,这可能会失败我猜 – 我不知道真的想要找出每个案件的适当行动。 我认为理想情况下,我想调用一些以A作为输入的函数,除了使select()返回之外什么都不做。 但是,我不知道这样的function。 (我想我可以例如shutdown()套接字,但副作用不是真的可以接受:) 如果这是不可能的,那么第二个最佳选择是创建一个比真正的UDP套接字更糟糕的B ,并且实际上并不需要分配任何有限的资源(超出合理的内存量)。 我想Unix域套接字就可以做到这一点,但是:解决方案不应该比现在的解决方案少得多,尽管有一些适量的#ifdef东西很好。 (我主要针对Windows和Linux – 并且顺便编写C ++。) 请不要建议重构以摆脱两个单独的线程。 这种设计是必要的,因为主线程可能会被长时间阻塞(例如,做一些密集的计算 – 我无法从最里面的计算循环开始定期调用receive() ),同时,有人需要缓冲传入的数据(由于我无法控制的原因,它不能是发送者)。 现在我正在写这篇文章,我意识到有人肯定会简单地回复“ Boost.Asio ”,所以我刚刚看了它……但是找不到明显的解决方案。 请注意,我也不能(轻松地)影响套接字A的创建方式,但如果需要,我应该能够让其他对象包装它。