发送二进制数据

5

循环执行send()时,第二个参数"const void *buf"是以二进制模式打开的文件描述符(fopen("C:\example.mp3", "rb")),这样做会有什么问题吗?


1
你的意思是想通过套接字发送文件内容吗?如果是这样,应该没有问题,但你需要将数据从文件中读取到缓冲区中,然后将缓冲区中的数据传输到套接字中。 - Jerry Coffin
1个回答

5
send的参数必须指向内存缓冲区,该缓冲区填充了您要发送的值(字节)。您可以将send()函数的参数const void *buf视为const char *buf - 它只是字符数组,不会被send()函数更改。

但是,fopen()会返回一个FILE* - 它是指向特殊结构FILE的指针。因此,如果您想发送文件的内容,则应使用fread()函数和FILE*指针将内容读入tmp缓冲区,然后将tmp缓冲区提供给send()函数。重复此代码,直到达到文件末尾。

示例代码(在http://developerweb.net/viewtopic.php?pid=28854找到)

int file2socket (FILE *fp, int sockfd)
{
    char tmp[8*1024];
    int len;
    int ret;

    for (ret = 0;;) {
        len = fread (tmp, 1, sizeof (tmp), fp);
        if (len == 0) {
            ret = feof (fp);
            break;
        }
        if (!send (sockfd, tmp, len, 0)) break;
    }

    return (ret);
}

在Linux上,还有一个系统调用sendfile,它实际上消除了用户空间并大大提高了速度 - http://www.kernel.org/doc/man-pages/online/pages/man2/sendfile.2.html - user405725
3
我会检查send函数的返回值。它可能会返回小于len的某个值,在这种情况下,您会想要使用tmp + r, len - r进行重试,其中r是先前发送的字节数。 - asveikau
在 Linux 上,有一个名为 splice 的系统调用取代了 sendfile - user611775
@user611775,我检查了splice系统调用。它的手册没有标记为过时。此外,glibc会正确翻译它,大多数用户不会直接进行系统调用(但我会),而是使用glibc。 - osgx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接