c - 未收到完整数据

标签 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. clien = sizeof(cli_addr); 需要在 accept() 调用上方的 while 循环内移动。

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

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

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

  5. 您的 printf() 调用仅输出 buffer 的前 4 个字节,而不是输出 buffer 的全部内容>。 read() 的返回值告诉您实际收到了多少字节。循环遍历 buffer,单独输出每个字节。

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

试试这个:

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);
    }
}

关于c - 未收到完整数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41492786/

相关文章:

c - 为什么要将指针转换为函数

c - 如何链接linux/gpio.h?

c - 需要透明类型的好处和情况是什么?

C 项目中的 C++ 静态库链接

.net - 如何使用powershell连接到tcp socket发送和接收数据?

sockets - 套接字编程-API怀疑

C# 控制台应用程序响应 HTTP POST 请求

php - MySQL 数据库无法启动 XAMPP

linux - header 中存在的 TCP 标志

Linux TCP : high Send-Q on sender, 接收器上的 Recv-Q 为零