Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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++ 如何正确地为ncurses进行epoll_C++_Sockets_Udp_Ncurses_Epoll - Fatal编程技术网

C++ 如何正确地为ncurses进行epoll

C++ 如何正确地为ncurses进行epoll,c++,sockets,udp,ncurses,epoll,C++,Sockets,Udp,Ncurses,Epoll,原始问题:我编写了一些客户端代码,用于监视键盘按下和服务器向其发送消息的sockfd。问题是,在服务器发出第一条消息后,服务器发出的消息不再触发epoll。此外,每次我输入大约10次按键,sockfd就会触发epoll并读取一组字符(即使服务器已经发送了很多消息)。更让我困惑的是,如果我一次只发送一个字符,epoll就能做出正确的反应。任何超过一个的,都将产生与以前相同的结果(epoll不反应) 编辑:我意识到如果我将STDIN_FILENO设置为非阻塞,我将在适当的时间从服务器获取消息。然而,

原始问题:我编写了一些客户端代码,用于监视键盘按下和服务器向其发送消息的sockfd。问题是,在服务器发出第一条消息后,服务器发出的消息不再触发epoll。此外,每次我输入大约10次按键,sockfd就会触发epoll并读取一组字符(即使服务器已经发送了很多消息)。更让我困惑的是,如果我一次只发送一个字符,epoll就能做出正确的反应。任何超过一个的,都将产生与以前相同的结果(epoll不反应)

编辑:我意识到如果我将STDIN_FILENO设置为非阻塞,我将在适当的时间从服务器获取消息。然而,该程序也将进入一个无限循环,而STDIN_总是被触发。我想现在的问题是如何正确地将epoll与ncurses结合使用,这样我们就不会处于无限循环中

这是我的密码:

如何使用:

  • clang++client.cpp-lncurses-o cli
  • clang++server.cpp-o ser
  • /ser 8080
  • 打开另一个终端
  • ./cli 127.0.0.1 8080
  • 我对epoll很陌生,所以恐怕我错过了一些东西。请让我知道我的代码有什么问题

    server.cpp:

    
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <chrono>
    #include <errno.h>
    #include <ifaddrs.h>
    #include <sys/epoll.h>
    
    #define TO_CLI_BUF_SIZE 32
    #define FROM_CLI_BUF_SIZE 8
    
    int main(int argc, char ** argv){
    
      //seed rand
      srand(time(NULL));
    
      int sockfd; // socket
      int port; // my port to listen on
      struct sockaddr_in serveraddr; // server's address
      struct sockaddr_in clientaddr;
      socklen_t clientlen;
      int currentAddrMax = 0;
      struct hostent * hostp; //host info
      char * hostaddrp; // host adddr string
      char toClientBuf[TO_CLI_BUF_SIZE];
      char fromClientBuf[FROM_CLI_BUF_SIZE];
    
      if(argc != 2){
        perror("usage: file <port>");
        exit(1);
      }
      port = atoi(argv[1]);
    
      // create socket
      sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      if(sockfd<0){
        perror("ERROR: opening socket.");
        exit(1);
      }
    
      bzero((char*) &serveraddr, sizeof(serveraddr));
      serveraddr.sin_family = AF_INET;
      serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
      serveraddr.sin_port = htons((unsigned short)port);
    
      if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){
        perror("ERROR on bind");
        exit(1);
      }
    
      bzero(fromClientBuf, FROM_CLI_BUF_SIZE);
      clientlen = sizeof(clientaddr);
      int n = recvfrom(sockfd, fromClientBuf,FROM_CLI_BUF_SIZE, 0, (struct sockaddr*) &clientaddr, &(clientlen));
    
      while (1){ 
        bzero(toClientBuf, TO_CLI_BUF_SIZE);
        strcpy(toClientBuf, "alkjhkfqulw8fl128lh1oufo183hf1l\0"); // I want to send 32 TO_CLI_BUF_SIZE
        int amountOfBytes = TO_CLI_BUF_SIZE; // anything greater than 1 will not work
        int n = sendto(sockfd, toClientBuf, amountOfBytes, 0, (struct sockaddr *) &clientaddr, clientlen);
        if(n < 0) {
          perror("ERROR in sendto");
          exit(1);
        }
    
        sleep(1); // sleep 1 sec
      }
    
      return 0;
    
    }
    
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义为大小32
    #从大小8定义
    int main(int argc,字符**argv){
    //种子兰德
    srand(时间(空));
    int sockfd;//套接字
    int-port;//要侦听的我的端口
    serveraddr中的struct sockaddr\u;//服务器地址
    clientaddr中的结构sockaddr_;
    socklen_t clientlen;
    int currentAddrMax=0;
    结构hostent*hostp;//主机信息
    char*hostaddrp;//主机adddr字符串
    char-TO-clientbuf[TO_CLI_BUF_SIZE];
    char fromClientBuf[来自CLI_BUF_SIZE];
    如果(argc!=2){
    perror(“用法:文件”);
    出口(1);
    }
    端口=atoi(argv[1]);
    //创建套接字
    sockfd=插座(AF_INET,SOCK_DGRAM,0);
    如果(sockfdh_地址,
    (char*)&serveraddr.sin\u addr.s\u addr,server->h\u length);
    serveraddr.sinu端口=htons(端口号);
    serverlen=sizeof(serveraddr);
    bzero(到服务器BUF,到服务器BUF大小);
    n=sendto(sockfd,toServerBuf,TO_seru BUF_SIZE,0,(struct sockaddr*)和serveraddr,serverlen);
    if(n<0){
    perror(“错误:发送到”);
    出口(0);
    }
    if(connect(sockfd,(struct sockaddr*)&serveraddr,serverlen)<0){
    printf(“\n错误:连接失败\n”);
    出口(0);
    } 
    fcntl(sockfd、F_设置FL、O_非块);
    节点延迟(stdscr,真);
    fcntl(标准文件号、固定格式、非块);
    initscr();
    noecho();
    int keyboardtick=0;
    int servertick=0;
    int ep=epoll_create1(0);
    结构epoll_事件e1,e2,e[2];//e1用于serverfd,e2用于stdin
    memset(&e1,0,sizeof(struct-epoll_事件));
    e1.events=EPOLLIN;
    e1.data.fd=sockfd;
    epoll控制(ep、epoll控制添加、sockfd和e1);
    memset(&e2,0,sizeof(struct-epoll_事件));
    e2.2事件=依泊林;
    e2.data.fd=标准数据文件号;
    epoll控制(ep、epoll控制添加、标准文件号和e2);
    mvprintw(0,0,“来自服务器的滴答声:%d”,服务器滴答声);
    mvprintw(2,0,“来自键盘的滴答声:%d”,键盘滴答声);
    而第(1)款{
    int n=epoll_wait(ep,e,2,-1);
    对于(int i=0;i
    您已选择使用具有此设置的边缘触发的
    epoll
    事件

    epoll手册页面详细讨论了它的含义,以及如何正确使用边缘触发的
    epoll
    事件。你应该回顾一下这个描述

    让我们继续:

        int n = epoll_wait(ep, e, 2, -1);
    
    // ...
            n = recvfrom(sockfd, fromServerBuf, FROM_SER_BUF_SIZE, 0,( struct sockaddr *) &serveraddr, &serverlen);
    
    如果
    epoll
    是由这个套接字从SER\u BUF\u SIZE
    接收的字节数超过
    而触发的,那么它只从SER\u BUF\u SIZE
    字节中读取第一个
    ——换句话说,发送方发送足够快的数据,这将从SER\u BUF\u SIZE
    字节中读取第一个
    。当返回到
    epoll\u wait
    ()时,它将再次等待。即使套接字上有更多数据需要读取。这就是边缘触发的
    epoll
    事件的工作方式。您正在以下描述边缘触发的epoll事件:

    问题是在服务器发出第一条消息后,epoll是no 由来自服务器的消息触发的时间更长。还有,每次我进去 按键10次左右,sockfd和1的epoll被触发 读取字符包(即使服务器已发送) 大量信息)

    对。您的
    epoll
    被边缘触发。所示逻辑仅使用第一个数据报,并再次调用
    epoll
    ,即使套接字有更多未读数据报

    更让我困惑的是,如果我一次只发送一个字符 随着时间的推移,epoll能够做出正确的反应。不止一个,威尔 结果与之前相同(epoll不起反应)

    请再说一遍。如果只发送一条消息,它将按照显示的逻辑进行处理,然后
    epoll
    再次等待

    边缘触发的epoll将等待事件再次在套接字上发生。句号。故事结束了。如果事件已在套接字上发生,则边缘触发的epoll将等待而不是立即返回。TLDR:如果套接字有未读数据,
    epoll\u wait
    ing for
    POLLIN
    将不会立即返回。它仅在获得更多数据后返回
    e1.events = EPOLLIN|EPOLLET;
    
        int n = epoll_wait(ep, e, 2, -1);
    
    // ...
            n = recvfrom(sockfd, fromServerBuf, FROM_SER_BUF_SIZE, 0,( struct sockaddr *) &serveraddr, &serverlen);