我正在尝试开发一个简单的应用程序,其中ONE Server将数据发送到ONE Client,使用select()在没有内容可读取时停止客户端 Activity 。
我能够发送/读取数据,但是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;
}

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

以下是客户端代码。
它接收并正确打印了所有数据,但是当服务器结束发送数据时,客户端继续打印字符串我没有在while循环中阻止,但是我希望它在select()系统调用之前停止,因为没有数据不再写在套接字上,因此文件描述符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);

            }
        }
    }
}

最佳答案

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

在您的代码中,您检查if (n == 0),什么也不做。您必须跳出那里的循环,因为闭合的插槽将保持就绪状态,直到闭合。

09-04 01:11
查看更多