c - 没有接收到数据,recv()返回0

标签 c sockets networking tcp

我正在编写我的第一个客户端/服务器程序。客户端发送文件名,服务器应发送该文件(如果存在)。 服务器:

while(1)
    {
        client_sock_fd = accept(listening_sock_fd, (struct sockaddr*)NULL, NULL);
        if (client_sock_fd == -1)
        {
            fprintf(stderr, "ERROR: accept()\n");
            continue;
        }

        if (!fork())
        {
            close(listening_sock_fd);

            if ((numbytes = recv(client_sock_fd, buff, 1023, 0)) == -1){
                fprintf(stderr, "ERROR: recv()\n");
                return EXIT_FAILURE;
            }

            buff[numbytes] = '\0';

            FILE *f = fopen(buff, "r");

            if (f == NULL){
                if ((send(client_sock_fd, "FAIL", 4, 0)) == -1)
                {
                    fprintf(stderr, "ERROR: send()\n");
                }
            }else {

                if ((send(client_sock_fd, "OK", 2, 0)) == -1)
                {
                    fprintf(stderr, "ERROR: send()\n");
                }

                char * buffer = 0;
                long length;


                fseek (f, 0, SEEK_END);
                length = ftell (f);
                fseek (f, 0, SEEK_SET);
                if((buffer = malloc (length)) == NULL){
                    fprintf(stderr, "ERROR: malloc()\n");
                    exit(1);
                }
                if (buffer)
                {
                    fread (buffer, 1, length, f);
                }
                fclose (f);


                char str[1024];
                sprintf(str, "%d", (int)strlen(buffer));
                if ((send(client_sock_fd, str, strlen(str), 0)) == -1)
                {
                    fprintf(stderr, "ERROR: send()\n");
                }

                int s = sendall(client_sock_fd, buffer, strlen(buffer));
                if (s == -1){
                    fprintf(stderr, "ERROR: send()\n");
                    free(buffer);
                    exit(1);
                }


                free(buffer);
            }

            close(client_sock_fd);
            exit(0);
        }
        close(client_sock_fd);
    }

int sendall(int s, char *buf, int len)
{
    int total = 0;
    int bytesleft = len;
    int n;

    while(total < len) {
        n = send(s, buf+total, bytesleft, 0);
        if (n == -1) { break; }
        total += n;
        bytesleft -= n;
    }

    return n==-1?-1:0;
} 

客户:

if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
        fprintf(stderr, "ERROR: chyba pri socket()\n");
        return EXIT_FAILURE;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(args.port_num);

    if ((prlHst = gethostbyname(argv[args.host_name])) == NULL){
        fprintf(stderr, "ERROR: gethostbyname()\n");
        return EXIT_FAILURE;
    }

    memcpy(&serv_addr.sin_addr, prlHst->h_addr_list[0], prlHst->h_length);

    if (connect(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
        fprintf(stderr, "ERROR: connect()\n");
        return EXIT_FAILURE;

if ((send(sock_fd, argv[args.file], strlen(argv[args.file]), 0)) == -1){
        fprintf(stderr, "ERROR: send()\n");
        return EXIT_FAILURE;
    }

    if ((numbytes = recv(sock_fd, buff, 1023, 0)) == -1){
        fprintf(stderr, "ERROR: recv()\n");
        return EXIT_FAILURE;
    }

    buff[numbytes] = '\0';

    FILE *fp = fopen(argv[args.file], "w");
    if (fp == NULL){
        fprintf(stderr, "ERROR: fopen()\n");
        return EXIT_FAILURE;
    }
    if (!strcmp(buff, "OK")){
        if ((numbytes = recv(sock_fd, buff, 1023, 0)) == -1){
            fprintf(stderr, "ERROR: recv()\n");
            return EXIT_FAILURE;
        }

        char *pEnd;
        long int dataToRead = strtol(buff, &pEnd, 10);
        long int readData = 0;

        fprintf(stderr, "data to read %lu\n", dataToRead);

        while (readData < dataToRead) {
            unsigned char buffer [4096] = {0};
            int nbuffer;
            for (nbuffer = 0; nbuffer < 4096; ) {

                int len = recv(sock_fd, buffer, 4096, 0);
                if (len == -1){
                    fprintf(stderr, "ERROR: recv()\n");
                    return EXIT_FAILURE;
                }
                /* FIXME: Error checking */

                nbuffer += len;
                readData += len;

            }

            fwrite(buffer, sizeof(unsigned char), nbuffer, fp);
        }

一切正常,直到客户端中的 while 循环为止。 recv 始终返回 0。这是为什么?我的代码有什么问题吗?我尝试用一​​次send向所需的文件写入一些内容,并且它被接收了。我还检查了 dataToRead 变量,它没问题,包含预期值。感谢您的回复!

最佳答案

Everything works fine until the while loop in client. recv always returns 0. Why is that?

这意味着对端已关闭连接。

What's wrong in my code?

您没有识别出这种情况,没有关闭套接字,也没有停止尝试从中读取数据。这是当 recv() 返回 0 时,或者实际上当它返回 -1 且 errno 等于除 EAGAIN/EWOULDBLOCK 之外的任何值时必须执行的操作.

I tried to write something to the wanted file send with one send and it was received. Also I checked dataToRead variable and it's ok, containing the expected value.

我不明白这有什么关系。

你的复制循环过于复杂。将字节从套接字传输到文件直到套接字上的流结束的规范方法如下:

while ((count = recv(socket, buffer, sizeof buffer)) > 0)
{
    write(file, buffer, count);
}

反之,将字节从文件传输到套接字:

while ((count = read(file, buffer, sizeof buffer)) > 0)
{
    send(socket, buffer, count);
}

关于c - 没有接收到数据,recv()返回0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36738073/

相关文章:

创建具有不同长度的静态数组

php - 使用 PHP 客户端连接到 websocket

c++ - C++ std::thread的行为

networking - 在 c/cpp 中寻找 tcp 堆栈实现(精化)

java - postgres服务器拒绝连接到heroku

java - 套接字连接半断开 - 未抛出 IOException

c - 检索在 root 下运行的进程中登录的用户名或 ID

c - 使用 bool 表达式代替 if/else 或类似条件

Python C Api 无提示地失败

sockets - 为什么用openssl编程时找不到 "TLSv1_3_client_method()"?