C-套接字:编程客户端/服务器 - 应用程序以发送文件

时间:2012-03-26 16:13:16

标签: c sockets client-server file-transfer

我想编写一个应用程序来发送带有套接字的文件:

这是我的服务器:

   void str_server(int sock)
    {
            char buf[1025];
            const char* filename="test.text";
            FILE *file = fopen(filename, "rb");
            err_abort("Test");
            while (!feof(file))
            {
                int rval = fread(buf, 1, sizeof(buf), file);
                send(sock, buf, rval, 0);
            }
    }

在这里我的客户:

void RecvFile(int sock, const char* filename)
{
    int rval;
    char buf[0x1000];
    FILE *file = fopen(filename, "wb");
    while ((rval = recv(sock, buf, sizeof(buf), 0)) > 0)
    {
        fwrite(buf, 1, rval, file);
    }
    close(sock);
}

我的问题是我的客户端创建了一个文件....但是不要在文件中写入内容!

1 个答案:

答案 0 :(得分:7)

为您的代码添加一些错误处理,这可以帮助您追踪问题。另请注意,send()recv()fread()fwrite()无法保证写入/读取您指定的整个缓冲区,因此您也应考虑到这一点。< / p>

此外,由于TCP是字节流,因此服务器需要指示文件何时结束,以便客户端知道何时停止读取。如果在发送实际文件之前没有发送文件大小,唯一的选择是在传输完成后关闭套接字。

尝试这样的事情:

int send_all(int sock, const void *buf, int len)
{
    const char *pbuf = (const char *) buf;

    while (len > 0)
    {
        int sent = send(sock, pbuf, len, 0);
        if (sent < 1)
        {
            // if the socket is non-blocking, then check
            // the socket error for WSAEWOULDBLOCK/EAGAIN
            // (depending on platform) and if true then
            // use select() to wait for a small period of
            // time to see if the socket becomes writable
            // again before failing the transfer...

            printf("Can't write to socket");
            return -1;
        }

        pbuf += sent;
        len -= sent;
    }

    return 0;
}

void str_server(int sock) 
{ 
    char buf[0x1000]; 
    const char* filename = "test.text";
    struct stat s;

    if (stat(filename, &s) == -1)
    {
        printf("Can't get file info"); 
        return;
    }

    FILE *file = fopen(filename, "rb"); 
    if (!file)
    {
        printf("Can't open file for reading"); 
        return;
    }

    // if you need to handle files > 2GB,
    // be sure to use a 64bit integer, and
    // a host-to-network function that can
    // handle 64bit integers...
    long size = s.st_size;
    long tmp_size = htonl(size);
    if (send_all(sock, &tmp_size, sizeof(tmp_size)) == 0)
    {
        while (size > 0)
        { 
            int rval = fread(buf, 1, min(sizeof(buf), size), file); 
            if (rval < 1)
            {
                printf("Can't read from file");
                break;
            }

            if (send_all(sock, buf, rval) == -1)
                break;

            size -= rval;
        }
    }

    fclose(file);
} 

int write_all(FILE *file, const void *buf, int len)
{
    const char *pbuf = (const char *) buf;

    while (len > 0)
    {
        int written = fwrite(pbuf, 1, len, file);
        if (written < 1)
        {
            printf("Can't write to file");
            return -1;
        }

        pbuf += written;
        len -= written;
    }

    return 0;
}

int read_all(int sock, void *buf, int len)
{
    char *pbuf = (char *) buf;
    int total = 0;

    while (len > 0)
    {
        int rval = recv(sock, pbuf, len, 0);
        if (rval < 0)
        {
            // if the socket is non-blocking, then check
            // the socket error for WSAEWOULDBLOCK/EAGAIN
            // (depending on platform) and if true then
            // use select() to wait for a small period of
            // time to see if the socket becomes readable
            // again before failing the transfer...

            printf("Can't read from socket");
            return -1;
        }

        if (rval == 0)
        {
            printf("Socket disconnected")
            return 0;
        } 

        pbuf += rval;
        len -= rval;
        total += rval;
    }

    return total;
}

void RecvFile(int sock, const char* filename) 
{ 
    int rval; 
    char buf[0x1000];

    FILE *file = fopen(filename, "wb"); 
    if (!file)
    {
        printf("Can't open file for writing");
        return;
    }

    // if you need to handle files > 2GB,
    // be sure to use a 64bit integer, and
    // a network-to-host function that can
    // handle 64bit integers...
    long size = 0;
    if (read_all(sock, &size, sizeof(size)) == 1)
    {
        size = ntohl(size);
        while (size > 0)
        {
            rval = read_all(sock, buf, min(sizeof(buf), size));
            if (rval < 1)
                break;

            if (write_all(file, buf, rval) == -1)
                break;
        } 
    }

    fclose(file); 
}