1

チャットクライアント用のサーバーを作成しています。問題が発生しているのは、次のとおりです。選択は、ネットクライアントが接続し、最後に接続したクライアントが書き込みを行っている場合にのみブロックを解除します。例:4つのクライアントが接続されている場合、サーバーはクライアント番号が表示されるまでブロックを続けます。クライアント1〜3が書き込みを行う場合、4は書き込みを行い、何が間違っているのかをブロックし続けますか?ここで分析するために、私のコードには醜くて役に立たないコードが含まれている可能性がありますが、それはその動作を分析しているだけです

Server.c ++

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <boost/thread/thread.hpp>
#include <sys/time.h>
#include <sys/ioctl.h>

using namespace std;

void error(char *msg, int socket) {
    perror(msg);
    close(socket);
    exit(1);
}

int main(int argc, char** argv) {
    int sockfd, newsockfd, portno, n, highsock;
    socklen_t clilen;
    fd_set readfds;
    list<int> CliSocks;
    FD_ZERO(&readfds);
    /*
     * Sockfd, newsockfd contain values returned by the socket
     * portno stores the port number on which the server accepts connections
     * clilen stores the size of the address of the client
     * n contains the amount of character written of read
     */
    char buffer[256];
    /* buffer contains the characters read from the socket*/

    struct sockaddr_in serv_addr, cli_addr;
    /* 
     * sockaddr_in contains an internet address
     * serv_addr contains the servers address
     * cli addr contains the clients address
     */
    if (argc < 2) {
        fprintf(stderr, "ERROR no port provided");
        exit(1);
    }
    /*
     * error if no argument
     */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    highsock = sockfd;
    FD_SET(sockfd, &readfds);
    int opt = 1;
    ioctl(sockfd, FIONBIO, &opt);

    if (sockfd < 0) {
        error("ERROR opening socket", sockfd);
    }
    /*
     * socket() creates a new socket
     * argument 1 contains the address domain
     * argument 2 contains the socket type
     * argument 3 contains the protocol should be 0
     * socket() returns a reference for itself
     */
    bzero((char*) &serv_addr, sizeof (serv_addr));
    /* empty the serv_addr variable*/
    portno = atoi(argv[1]);
    /*converts the port argument from string  to int*/
    serv_addr.sin_family = AF_INET;
    /*set the code for the address family*/
    serv_addr.sin_port = htons(portno);
    /*htons converts the portno to network bytes and gives it to the server address*/
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    /*set the server ip to the ip of the running machine*/
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
        error("ERROR on binding", sockfd);
    /*
     * bind() binds a socket to an address, in this case the
     * addess of the current host
     */
    listen(sockfd, 5);

    /*the listen system call allows the process to listen on the socket for connections*/


    while (1) {
        int sockcount = select(highsock + 1, &readfds, NULL, NULL, NULL);

        clilen = sizeof (cli_addr);
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        /*
         * accept() lets the system wait until a client connects to the server
         */

        if (newsockfd > 0) {
            ioctl(newsockfd, FIONBIO, &opt);
            FD_SET(newsockfd, &readfds);
            highsock = newsockfd;
            CliSocks.push_back(newsockfd);
        }


        for (list<int>::iterator it = CliSocks.begin(); it != CliSocks.end(); it++) {
            bzero(buffer, 256);
            n = read(*it, buffer, 255);
            if(buffer[0] != 0){
            printf("Here is the message: %s", buffer);

            /*
             * bzero empties the buffer
             * read obviously reads data from the new socket descriptor
             */
            n = write(*it, "I got your message", 18);
            if (n < 0) error("ERROR writing to socket", sockfd);
                        }
        }
    }
    close(sockfd);
    return 0;
}
4

1 に答える 1

2

readfds問題は、を呼び出す前に、ループ内で毎回リセットする必要があることですselect。これは、の呼び出しがそのパラメーターをselect 変更するためです。

while (1) {
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);
    highsock = sockfd;
    for (list<int>::iterator it = CliSocks.begin(); it != CliSocks.end(); it++) {
        FD_SET(*it, &readfds);
        highsock = *it > highsock ? *it : highsock;
    }
    int sockcount = select(highsock + 1, &readfds, NULL, NULL, NULL);

    ...
}
于 2012-10-26T11:47:50.307 に答える