一台将数据发送到一个客户端的服务器。使用select()具有非阻塞I / O

时间:2018-07-23 12:45:54

标签: c++ linux select

我正在尝试开发一个简单的应用程序,其中ONE Server将数据发送到ONE客户端,并在select()停止读取任何内容时使用select()停止客户端活动。 我能够发送/读取数据,但是select()系统调用似乎没有作用,因为当服务器的写入操作完成时,客户端不会在select()系统调用之前停止并继续执行执行printf之后的操作(在这种情况下为void initSocket() { printf("socket initialized\n"); sockFd = socket(AF_INET, SOCK_STREAM, 0); if (sockFd < 0) sockError("ERROR opening socket"); bzero((char*)&servAddr, sizeof(servAddr)); portNum = 7550; servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = INADDR_ANY; servAddr.sin_port = htons(portNum); if (bind(sockFd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0) sockError("ERROR on blinding"); listen(sockFd, 5); cliLen = sizeof(clientAddr); newsockFd = accept(sockFd, (struct sockaddr*)&clientAddr, &cliLen); if (newsockFd < 0) sockError("ERROR on accept"); printf("Request received\n"); } void sendGpsCoord(char* line) { int n; n = write(newsockFd, line, sizeof(nmeaPOS)); if (n < 0) printf("ERROR in writing socket"); } void closeSocket() { close(newsockFd); close(sockFd); printf("sockets closed\n"); } int main() { printf("main started\n"); initSocket(); char line[256]; while (fgets(line, sizeof(line), stdin) != NULL) { sendGpsCoord(&line); } closeSocket(); return 0; } )。

这是服务器代码

select()

工作正常。它发送文件中的所有数据,然后退出。


以下是客户端代码。 它会正确接收和打印所有数据,但是当服务器结束发送数据时,客户端会继续在while循环中打印字符串我没有阻止,而我希望它在{{ 1}}系统调用,因为套接字上不再写入任何数据,因此文件描述符gpsSockRight不应再更改。

 fd_set readSetRight;
 struct sockaddr_in gpsServAddrLeft;
 int gpsServPortRight = 7550;
 int gpsSockRight;



 bool initGpsSocket()
 {
     bool ret = false;

     gpsSockRight = socket(AF_INET, SOCK_STREAM, 0);
     if (gpsSockRight < 0) {
         error("ERROR opening socket");
         ret = true;
     }

     gpsServRight = gethostbyname("192.168.2.91");

     bzero((char *) &gpsServAddrRight, sizeof(gpsServAddrRight));
     gpsServAddrRight.sin_family = AF_INET;

     bcopy((char *)gpsServRight->h_addr, 
           (char *)&gpsServAddrRight.sin_addr.s_addr,
           gpsServRight->h_length);

     gpsServAddrRight.sin_port = htons(gpsServPortRight);

     if (connect(gpsSockRight, (struct sockaddr *)   
         &gpsServAddrRight,sizeof(gpsServAddrRight)) < 0) {

         error("ERROR connecting");
         ret = true;
     }

     // To set the socket to be non blocking
     int on = 1;
     ioctl(gpsSockRight, FIONBIO, (char*)&on);

     return ret; 
}

void runGpsSocketRight()
{
    int n;
    string line;

    while(gRun) {  
        FD_ZERO(&readSetRight);
        FD_SET(gpsSockRight, &readSetRight);

        if (select(gpsSockRight +1 , &readSetRight, NULL, NULL, NULL) < 0) {
            error("select\n");
            exit(1);
        }

        printf("I'm not blocking\n");

        if (FD_ISSET(gpsSockRight, &readSetRight)) {
            FD_CLR(gpsSockRight, &readSetRight);
            n = read(gpsSockRight, &line, sizeof(line));
            if (n < 0)
                error("ERROR reading from socket");
            else if (n == 0)
                ;
            else if (n > 0) {
                printf("Here is the line: %s\n", line);

            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

当套接字关闭时选择返回,因为EOF将套接字标记为可读取。随后的读取返回大小为0,显示套接字在另一侧已关闭。

在您的代码中,您选中if (n == 0)并且不执行任何操作。您必须跳出那里的循环,因为封闭的插槽将保持可读状态,直到关闭。