不接收数据,recv()返回0

时间:2016-04-20 08:31:12

标签: 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变量,它没有,包含预期的值。谢谢你的回复!

1 个答案:

答案 0 :(得分:0)

  

一切正常,直到客户端的while循环。 recv总是返回0。    那是为什么?

这意味着对等方已关闭连接。

  

我的代码出了什么问题?

您无法识别该情况,关闭套接字并停止尝试从中读取。这是recv()返回0时必须执行的操作,或者实际返回-1时errno等于EAGAIN/EWOULDBLOCK以外的任何内容。

  

我试图通过一次发送向所需文件发送内容并收到它。我还检查了dataToRead变量,它没有,包含预期的值。

我看不出这与它有什么关系。

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

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

反过来将字节从文件传输到套接字:

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