Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在使用Poll()的TCP服务器-客户端连接中,是否需要手动设置事件?我从来不会伸手去给插座写东西_C++_C_Sockets_Networking - Fatal编程技术网

C++ 在使用Poll()的TCP服务器-客户端连接中,是否需要手动设置事件?我从来不会伸手去给插座写东西

C++ 在使用Poll()的TCP服务器-客户端连接中,是否需要手动设置事件?我从来不会伸手去给插座写东西,c++,c,sockets,networking,C++,C,Sockets,Networking,我在一个fd上使用poll()在c中的客户端和服务器之间建立了连接。我希望客户端在服务器有东西要发送时接收消息,反之亦然 据我所知,poll()侦听文件描述器上的事件。我不清楚这些事件(或复仇者)是如何触发的,以确定何时在fd上发送或接收 我曾尝试在客户端的循环中使用读写(或发送和接收),但它们会阻塞,所以我也切换到了客户端的poll() 在客户端,我永远不会使用}else if(fds[0].revents&POLLOUT)部分,这意味着套接字永远无法写入 //Create - bind

我在一个fd上使用poll()在c中的客户端和服务器之间建立了连接。我希望客户端在服务器有东西要发送时接收消息,反之亦然

据我所知,poll()侦听文件描述器上的事件。我不清楚这些事件(或复仇者)是如何触发的,以确定何时在fd上发送或接收

我曾尝试在客户端的循环中使用读写(或发送和接收),但它们会阻塞,所以我也切换到了客户端的poll()

在客户端,我永远不会使用
}else if(fds[0].revents&POLLOUT)
部分,这意味着套接字永远无法写入

   //Create - bind - listen to a socket named listeningSocket

    struct pollfd fds[1];
    fds[0].fd = listeningSocket;
    fds[0].events = POLLIN | POLLPRI;


 if (poll(fds, 1, 3000)) {
            (client_sock = accept(listeningSocket, &client, (socklen_t *) &c));
            spdlog::info("Connection accepted");

            std::thread thread(&ConnectionHandler::Handle, std::ref(requestHandler), client_sock);
            thread.detach();

}

客户端块


 while (true) {
        if ((rv = poll(fds, 1, 100) > 0)) {

            if (fds[0].revents & POLLIN ){
                recv(sockfd, buff, 200, 0);
                printf("From Server : %s", buff);
                bzero(buff, sizeof(buff));

            }
        }else if (fds[0].revents & POLLOUT){
            puts(buff);
            strcpy(buff, "HELLO WORLD");
            write(sockfd, buff, sizeof(buff));
            break;
        }
    }


连接时,服务器向客户端发送一条带有
write()
的欢迎消息。客户机
recv()
s这一点,但之后再也不会转向右回到服务器


我错过什么了吗?当套接字上没有要接收的延迟数据时,它不应该准备好写入吗?

之前删除
}
,如果
,则删除

然后将其放在
else if
-块之后。

允许在
循环时重新格式化
,以使其更易于阅读:

while(true)
{
如果((rv=poll(fds,1100)>0))
{
if(fds[0]。revents和POLLIN)
{
recv(sockfd,buff,200,0);
printf(“来自服务器:%s”,buff);
bzero(buff,sizeof(buff));
}
}
else if(fds[0]。收回和轮询)
{
放置(buff);
strcpy(buff,“你好,世界”);
写入(sockfd、buff、sizeof(buff));
打破
}
}
现在应该很清楚为什么您的
POLLOUT
块从未执行过-如果只有在
poll()
返回
0]时才到达
if
语句) { if(fds[0]。revents和POLLIN) { recv(sockfd,buff,200,0); printf(“来自服务器:%s”,buff); bzero(buff,sizeof(buff)); } else if(fds[0]。收回和轮询) { 放置(buff); strcpy(buff,“你好,世界”); 写入(sockfd、buff、sizeof(buff)); 打破 } } }
当重新格式化为原始编码样式时,将如下所示:

while(true){
如果((rv=poll(fds,1100)>0)){
if(fds[0]。revents和POLLIN){
recv(sockfd,buff,200,0);
printf(“来自服务器:%s”,buff);
bzero(buff,sizeof(buff));
}else if(fds[0]。收回和轮询){
放置(buff);
strcpy(buff,“你好,世界”);
写入(sockfd、buff、sizeof(buff));
打破
}
}
}
看到好的格式有什么不同吗

也就是说,要知道套接字一连接就进入可写状态。因此,您的代码可能会在等待服务器的问候语之前发送客户端的问候语。如果在回复之前需要等待服务器的问候语,则必须首先阅读问候语,例如:

while(true)
{
如果((rv=poll(fds,1100)>0))
{
if(fds[0]。revents和POLLIN)
{
rv=recv(sockfd,buff,200,0);
如果(0))
{
if(fds[0]。revents和POLLIN)
{
rv=recv(sockfd,buff,200,0);
如果(rv 0)
{
rv=发送(fd,pdata,len,0);
如果(rv<0)
打破
pdata+=rv;
len-=rv;
发送+=rv;
}
如果(已发送>0)
{
//从fd的缓冲区中删除发送的字节。。。
}
}
}
}

然后,您可以在需要将任何数据发送到
fd
的任何时候使用
sendData()
,而不是直接调用
write()
/
send()

您忽略了
recv
的返回值,这绝不是一个好主意。另外,为什么
sizeof(buff)
to
write
?@DavidSchwartz此示例代码已取消了许多检查(例如recv返回值),其范围更多地是一个库,而不是一个独立的程序(因此是sizeof(buff)。您不知道要发送的消息有多大)。任何想法或改进都是好的。如果你不知道要发送的消息有多大,你怎么能发送它?你不需要知道要发送正确的字节数要发送多少字节吗?!非常感谢你的努力。我确实看到了良好的格式使错误更容易被发现。我有一个问题要问你r回答:我怎么知道我什么时候收到了整封邮件?再次感谢您的时间和努力!@kaptsea这就是协议的意义所在。发送方必须以接收方知道何时收到全部邮件的方式格式化其邮件。对于TCP,只有3种方法可以做到这一点:1)在收到之前发送邮件长度e发送消息数据。首先读取长度,然后读取长度所表示的字节数。2)在数据之后发送一个唯一的终止符。继续读取,直到接收到终止符。3)关闭连接。继续读取,直到断开连接。因此,您需要编写代码,以匹配服务器使用的任何协议。让我直说吧;我可以事先决定每条消息将以“\n”结尾或一定的长度,然后读取-recv,直到满足任一标准?这都是我的决定?在这方面没有一些最佳实践吗?哪种是最常见的实现方式?@kaptsea如果您同时编写客户端和服务器,那么是的,这是您的决定,所以请使用适合的方法您的需要。长度前缀适用于可变长度二进制数据,使用终止符适用于文本bas