未收到完整数据

时间:2017-01-05 19:07:07

标签: c sockets tcp

我在C中有以下套接字代码。我试图在每个循环中接收70个字节的数据。但是,我只获得4个字节的数据。完整数据是这样的(十六进制):

4D43475000856308000004B2DE1F04009E00200100000000696CF7AB002F1A00000000
000000325C000402069BFDE70857E22502F41C000036000000DF0B0932100B09DC0719

有什么问题?我试图研究许多StackOverflow答案,但没有任何帮助。

代码如下:

void doprocessing (int sock);

int main( int argc, char *argv[] ) {
    int sockfd, newsockfd, portno, clilen;
    char buffer[1024];
    struct sockaddr_in serv_addr, cli_addr;
    int n, pid;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd < 0) {
        perror("ERROR opening socket");
        exit(1);
    }

    /* Initialize socket structure */
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = 14064;

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    /* Now bind the host address using bind() call.*/
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        perror("ERROR on binding");
        exit(1);
    }

    /* Now start listening for the clients, here
     * process will go in sleep mode and will wait
     * for the incoming connection
    */

    listen(sockfd,5000);
    clilen = sizeof(cli_addr);

    while (1) {
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

        if (newsockfd < 0) {
            perror("ERROR on accept");
            exit(1);
        }

        /* Create child process */
        pid = fork();

        if (pid < 0) {
            perror("ERROR on fork");
            exit(1);
        }

        if (pid == 0) {
            /* This is the client process */
            close(sockfd);
            doprocessing(newsockfd);
            exit(0);
        }
        else {
            close(newsockfd);
        }

    } /* end of while */
}

void doprocessing (int sock) 
{
    int n,i;
    unsigned int *buffer = malloc(1024);

    n = read(sock,buffer,1023);

    if (n < 0) {
        perror("ERROR reading from socket");
        exit(1);
    }

    printf("Here is the message: %.4x\n",*buffer);

    n = write(sock,"MCGP",18);

    if (n < 0) {
       perror("ERROR writing to socket");
       exit(1);
    }
    free(buffer);
}

1 个答案:

答案 0 :(得分:3)

您的代码中存在大量错误:

  1. clilen = sizeof(cli_addr);需要在while来电之上的accept()循环内移动。

  2. unsigned int *buffer应该是unsigned char *buffer

  3. 当你只期望70个字节时,为什么要读取1023个字节?

  4. 您需要在循环中调用read(),直到您实际收到所需的所有字节为止。 read()可以返回比请求的字节少的字节。 TCP是字节流,它没有消息边界的概念,读取将返回当前可用的任何字节,因此它将返回至少 1字节直到所请求的字节数。

  5. 您的printf()来电仅输出buffer的前4个字节,而不会输出buffer的完整内容。 read()的返回值告诉您实际接收的字节数。循环遍历buffer分别输出每个字节。

  6. write(sock,"MCGP",18)是一个缓冲区溢出,因为你只传递了5个字节(4个字符和空终止符),但却告诉它发送18个字节。

  7. 请改为尝试:

    void doprocessing (int sock);
    
    int main( int argc, char *argv[] ) {
        int sockfd, newsockfd, portno;
        struct sockaddr_in serv_addr, cli_addr;
        socklen_t clilen;
        int pid;
    
        sockfd = socket(AF_INET, SOCK_STREAM, 0);   
        if (sockfd < 0) {
            perror("ERROR creating socket");
            exit(1);
        }
    
        /* Initialize socket structure */
        bzero((char *) &serv_addr, sizeof(serv_addr));
        portno = 14064;
    
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(portno);
    
        /* Now bind the host address using bind() call.*/
        if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
            perror("ERROR on bind");
            exit(1);
        }
    
        /* Now start listening for the clients, here
         * process will go in sleep mode and will wait
         * for the incoming connection
        */
    
        if (listen(sockfd, SOMAXCONN) < 0) {
            perror("ERROR on listen");
            exit(1);
        }
    
        while (1) {
            clilen = sizeof(cli_addr);
    
            newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
            if (newsockfd < 0) {
                perror("ERROR on accept");
                exit(1);
            }
    
            /* Create child process */
            pid = fork();
    
            if (pid < 0) {
                perror("ERROR on fork");
                exit(1);
            }
    
            if (pid == 0) {
                /* This is the client process */
                close(sockfd);
                doprocessing(newsockfd);
                exit(0);
            }
            else {
                close(newsockfd);
            }
    
        } /* end of while */
    }
    
    void doprocessing (int sock) 
    {
        int n, i;
        unsigned char buffer[70], *p = buffer;
        size_t len = 70;
    
        do {
            n = read(sock, p, len);
            if (n < 0) {
                perror("ERROR reading from socket");
                exit(1);
            }
    
            if (n == 0) {
                perror("DISCONNECTED unexpectedly");
                exit(1);
            }
    
            p += n;
            len -= n;
        }
        while (len > 0);
    
        printf("Here is the message: ");
        for (i = 0; i < 70; ++i)
            printf("%.02x", buffer[i]);
        printf("\n");
    
        n = write(sock, "MCGP", 4);
        if (n < 0) {
           perror("ERROR writing to socket");
           exit(1);
        }
    }