当没有数据可从套接字读取时读取块

时间:2019-05-20 19:09:14

标签: c sockets server

我出于教育目的而实现服务器/客户端应用程序。我的服务器打开一个套接字,并对其进行轮询以进行连接。如果有可用的连接,它将接受并发送一些数据。然后它等待输入并再次发送一些数据。

在实现客户端时,我尝试立即写入套接字,但这没有用。我必须先接收服务器告诉我的内容,然后再发送一些数据。然后等待再次接收。

这似乎不是一个好的解决方案,并且由于这是一个教育性项目,所以我想知道如何将其抽象化(即不在乎服务器将向我发送内容的次数以及我将其发送回去的次数。 )

到目前为止,我已经尝试过循环以接收服务器的输入,但是没有成功。服务器向套接字写入两次,因此客户端在尝试发送自己的消息之前必须读取两次。如果我第三次阅读,则阅读会阻塞(我认为这是正常行为)。

我尝试从客户端使用套接字上的poll来监视POLLOUT事件,但这似乎不起作用。

int connect(){

    unsigned int backlog = 10;

/*
    struct sockaddr_in {
        short            sin_family;   // e.g. AF_INET
        unsigned short   sin_port;     // e.g. htons(3490)
        struct in_addr   sin_addr;     // see struct in_addr, below
        char             sin_zero[8];  // zero this if you want to
    };

    struct in_addr {
        unsigned long s_addr;  // load with inet_aton()
    };
*/

    struct sockaddr_in server{};

    //Create socket
    listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (listeningSocket == -1) {
        spdlog::critical("Could not create socket");
    }

    spdlog::debug("Socket created.");

    //Prepare the socket for incoming connections
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(PortNumber); // NOLINT(hicpp-signed-bitwise)

    if (bind(listeningSocket, (const struct sockaddr *) &server, sizeof(sockaddr_in)) < 0) {
        spdlog::critical("bind failed. Error");
        exit(-1);
    }

    spdlog::debug("Bind succeeded\n");

    if (!listen(listeningSocket, static_cast<int>(backlog))) {
        return listeningSocket;
    }

    return -1;
}

处理消息

void* sendMessage(){

    //Get the socket descriptor
    int sock = socket;
    int read_size;
    const char *message;
    char client_message[200];

    //Send some messages to the client
    message = "Greetings! I am your connection handler\n";
    write(sock, message, strlen(message));

    message = "Now type something and i shall apply the caesar cipher to it \n";
    write(sock, message, strlen(message));

    //Receive a message from client
    while ((read_size = recv(sock, client_message, 200, 0)) > 0) {
        //end of string marker
        client_message[read_size] = '\0';

        std::string temp(client_message);
        temp = cipher->operate(temp);

        //Send the message back to client
        write(sock, temp.c_str(), strlen(temp.c_str()));

        //clear the message buffer
        memset(client_message, 0, 200);
    }

    if (read_size == 0) {
        spdlog::debug("Client disconnected");
        fflush(stdout);
    } else if (read_size == -1) {
        spdlog::error("recv failed: {}",errno);
    }

    return nullptr;

}

对于客户端:

//Connect to the server 

void connect()
 {
        struct hostent *he;
        struct sockaddr_in their_addr{}; /* connector's address information */

        if ((he=gethostbyname(mHost.c_str())) == nullptr) {  /* get the host info */
            spdlog::error("gethostbyname");
        }

        if ((mSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            spdlog::error("socket");
            exit(1);
        }

        their_addr.sin_family = AF_INET;      /* host byte order */
        their_addr.sin_port = htons(mPort);    /* short, network byte order */ //NOLINT
        their_addr.sin_addr = *((struct in_addr *)he->h_addr);
        bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */

        if (connect(mSocket, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
            spdlog::error("connect");
            exit(1);
        }
}

}

并尝试发送消息:

void sendMessage(){

#define MAX 100

    if (!sockfd) {
        sockfd = mSocket;
        spdlog::info("Setting socket to {}", sockfd);
    }

    char buff[MAX];
struct pollfd fds[1];
fds[0].fd=sockfd;



    while (( recv(sockfd, buff, 200, 0)) > 0) {

        printf("From Server : %s", buff);
        bzero(buff, sizeof(buff));
    }

    strcpy(buff, "PAPARI");
    write(sockfd, buff, sizeof(buff));
    bzero(buff, sizeof(buff));

    read(sockfd, buff, sizeof(buff));
    printf("From Server : %s", buff);


    close(sockfd);

}

这将在客户端收到来自服务器的两条消息后阻塞。

0 个答案:

没有答案