精华内容
下载资源
问答
  • 什么是流式传输

    千次阅读 2021-03-01 21:31:59
      而采用流媒体技术,就可实现流式传输,将声音、影像或动画由服务器想用户计算机进行连续、不间断传输,用户不必等到整个文件全部下载完毕,而只需要经过几秒或十几秒的启动延时即可进行观看。当声音视频等在用户...

      传统的网络传输音视频等多媒体信息的方式是完全下载后在播放,下载常常需要花数分钟甚至数小时。

      而采用流媒体技术,就可实现流式传输,将声音、影像或动画由服务器想用户计算机进行连续、不间断传输,用户不必等到整个文件全部下载完毕,而只需要经过几秒或十几秒的启动延时即可进行观看。当声音视频等在用户的机器上播放时,文件的剩余部分还会从服务器上继续下载。

      网络协议:http,rtmp,rtsp,rtp/rtcp,udp,tcp

      如果将文件传输看做一次水流的过程,过去的传输就像对用户做了一个规定,必须等到一桶水接满才能使用它,这个等待的时间自然要受到水流大小和桶的大小的影响。

      流式传输,就比如,打开水龙头,等待一会儿,水就会源源不断地流出来,而且可以随接随用,因此,不管水流量的大小,也不管桶的大小,用户都可以随时用上水。从这个意义上看,流媒体这个词是非常形象的。

      流试传输时,声音、影响或动画片等时基媒体由音视频服务器向用户计算机的连续、实时传送,用户不必等到整个文件全部下载完毕,而只需经过几秒或十几秒的启动延时既可进行观看。当声音等时基媒体在客户机上播放时,文件的剩余部分将在后台从服务器内继续下载。流式不仅使启动延时成十倍、百倍地缩短,而且不需要太大的缓存容量。流式传输避免了用户必须等待整个文件全部从 Internet 上下载才能观看的缺点。
      在运用流媒体技术时,音视频文件采用响应的格式,不同格式的文件需要用不同的播放器软件来播放,所谓“一把钥匙开一把锁”。

    1. Itu:h.261,3,4,5
    2. Iso:mpeg1,2,4
    3. Rtmp/rtsp/rtp/…

      流式传输定义很广泛,现在主要通过网络传输媒体(如视频、音频)的技术总称。其特定含义通过Internet将影视节目传送到PC机。

      实现流式传输有两种方法:实时流式传输(Realtime streaming)和 顺序流式传输(progressive streaming)。

      a.顺序流式传输是顺序下载,在下载文件的同时用户可观看在线媒体,在给定时刻,用户只能观看已下载的那部分,而不能跳到还未下载的前头部分,顺序流式传输不象实时流式传输在传输期间根据用户连接的速度做调整。

      Nginx,Web服务器,mp4文件/flv/mov/mkv/ts/rmvb/http
      由于标准的 HTTP 服务器(nginx ,apache ,tomcat ,iis)可发送这种形式的文件,也不需要其他特殊协议,它经常被称作 HTTP 流式传输。
      顺序流式传输比较适合高质量的短片段,如片头、片尾和广告,由于该文件在播放前观看的部分是无损下载的,这种方法保证电影播放的最终质量。这意味着用户在观看前,必须经历延迟,对较慢的连接尤其如此。对通过调制解调器发布短片段,顺序流式传输显得很实用,它允许用比调制解调器更高的数据速率创建视频片段。尽管有延迟,毕竟可让你发布较高质量的视频片段。
      顺序流式文件是放在标准HTTP或FTP服务器上,易于管理,基本上与防火墙无关。
      但是顺序流式传输不适合长片段和有随机访问要求的视频,如讲座、演说与演示。它支持现场广播,严格说来,它是一种点播技术。

      b.实时流式传输指保证媒体信号带宽与网络连接配匹,使媒体可被实时观看到。实时流与 HTTP 流式传输不同,他需要专用的流媒体服务器与传输协议。实时流式传输总是实时传送,特别适合现场事件,也支持随机访问,用户可快进或后退以观看前面或后面的内容。Realtime transfer protocol : RTP/rtcp理论上,实时流一经播放就可不停止,但实际上,可能发生周期暂停。实时流式传输必须配匹连接带宽,这意味着在以调制解调器速度连接时图象质量较差。而且,由于出错丢失的信息被忽略掉,网络拥挤或出现问题时,视频质量很差。如欲保证视频质量,顺序流式传输也许更好。

      实时流式传输需要特定流媒体服务器,如 QuickTime Streaming Server、RealServer 与
    Windows Media Server。这些服务器允许你对媒体发送进行更多级别的控制,因而系统设置、管理比标准 HTTP 服务器更复杂。
      实时流式传输还需要议特殊网络协议,如:RTSP (Realtime Streaming Protocol)或 MMS(Microsoft Media Server)。这些协议在有防火墙时有时会出现问题,导致用户不能看到一些地点的实时内容。
      一般说来,如视频为实时广播,或使用流式传输媒体服务器,或应用如 RTSP 的实时协
    议,即为实时流式传输。如使用 HTTP 服务器,文件即通过顺序流发送。采用那种传输方法依赖你的需求。当然,流式文件也支持在播放前完全下载到硬盘。

    在这里插入图片描述

    展开全文
  • 网络尾巴 在浏览器中实时流式传输文件。 使用websockets进行数据传输。 如何 在config.json指定要流式传输的文件。 启动服务器: npm start
  • 数据下载和流式传输的区别

    千次阅读 2008-12-18 09:41:00
    在网络上传输音频、视频等多媒体数据,目前主要有下载和流式...而采用流式传输,多媒体信息可由服务器向用户计算机连续实时地传送,用户不必等到整个文件全部下载完毕,只需经过几秒或十几秒的启动延时即可进行观看。
    在网络上传输音频、视频等多媒体数据,目前主要有下载和流式传输两种方案。下载的缺点是:必须等全部内容传输完毕后,才能在本地机器打开;而采用流式传输,多媒体信息可由服务器向用户计算机连续实时地传送,用户不必等到整个文件全部下载完毕,只需经过几秒或十几秒的启动延时即可进行观看。
    展开全文
  • 在世界地图上实时流式传输实时推文。 此网络应用程序附加到并使用开源Python库 (充当Twitter API的传播者)来提取带有地理数据的推文。 安装和运行 为安装服务器端框架。 pip install flask 克隆仓库 ...
  • 实时Kafka连接器以流式传输传感器数据 用法 设置配置 在opensensors.io中设置用户 创建至少2个设备和一些主题 编辑kafka-connector.yml并更新 client_id device_password username consume_topics 构建kafka连接...
  • Web浏览器启动音视频客户程序,使用HTTP从Web服务器检索相关参数对音视频客户程序初始化,这些参数可能包括目录信息、音视频数据的编码类型或与音视频检索相关的服务器地址; 音视频客户端程序及音视频服务器运行...
    1. 用户选择某一流媒体服务后,Web浏览器与Web服务器之间使用HTTP/TCP交换控制信息,以便把需要传输的实时数据从原始信息中检索出来;
    2. Web浏览器启动音视频客户程序,使用HTTP从Web服务器检索相关参数对音视频客户程序初始化,这些参数可能包括目录信息、音视频数据的编码类型或与音视频检索相关的服务器地址;
    3.  音视频客户端程序及音视频服务器运行实时流协议,以交换音视频传输所需的控制信息,实时流协议提供执行播放、快进、快倒、暂停及录制等命令的方法;
    4. 音视频服务器使用RTP/UDP协议将音视频数据传输给音视频客户程序,一旦音视频数据抵达客户端,音视频客户程序即可播放输出。
    5. 在流式传输中,使用 RTP/UDP和RTSP/TCP两种不同的通信协议与音视频服务器建立联系,目的是为了能够把服务器的输出从定向到一个非运行音视频客户程序的客户机的目的地址。

        

    转载于:https://www.cnblogs.com/Mylimo/archive/2012/02/16/2352231.html

    展开全文
  • 在交互式监视模式下启动测试运行程序。 有关更多信息,请参见关于的部分。 npm run build 构建生产到应用程序build文件夹。 它在生产模式下正确捆绑了React,并优化了构建以获得最佳性能。 最小化构建,文件名...
  • 使用和从桌面捕获音频和视频并将其流式传输到本地网络。 Python脚本 您可以只运行python模块,并且-如果安装此软件包-也可以从控制台或桌面外壳启动提供的脚本。 用法 像python -m desktopstreamer [options]这样...
  • 配置,启动和管理多个WebSocket或SSE服务器 发送数据到连接的客户端 计划数据流以发送连接的客户端 服务器配置的永久本地存储 入门 分叉并克隆Socketcast存储库 安装节点依赖项 npm i 捆绑应用 npm run build ...
  • 停止或启动时自动保存装备 附加并扩展单独的游戏驱动器 选择g2.2xlarge,g3s.xlarge或g3.4xlarge实例类型 有两种使用cloudRIG的方法: 或 。 注:我强烈建议您使用专用的AWS占cloudRIG描述。 屏幕截图 命令行界面 ...
  • 这是一组docker容器,用于运行易于部署的流式站点。 我用它来为大流行期间的事件提供直播。 它由具有rtmp支持的nginx和两个用作缓存服务器的常规nginx组成。 他们减少了主(入口)服务器上的网络负载。 如何运行此...
  • 首次启动OBS时,将启动自动配置向导。 为FPS选择1920x1080的Base (Canvas) Resolution和30 。 对于这两者,最好不要Use Current版本”,而只能使用这些值。 由于已在此处设置了分辨率和帧频,因此其他设置也将遵循...
  • 用户搜索将首先发送到firestore,如果在firestore中找不到搜索,则将调用scraper(python scrapy框架)以启动抓取过程。 抓取工具抓取数据后,抓取的数据将发送到Firestore。 使用firestore实时更新,vue界面将...
  • 微型高性能服务器,在节点处理块时将其流式传输到套接字,以供其他进程接收。 这个包并不是要单独使用,而是其他纳nano-stream npm包的基础库,这些纳nano-stream npm包接收该流并将其转换为其他内容。 看: ...
  • 在交互式监视模式下启动测试运行器。 有关更多信息,请参见关于的部分。 yarn build 构建生产到应用程序build文件夹。 它在生产模式下正确捆绑了React,并优化了构建以获得最佳性能。 生成被最小化,并且文件名...
  • 这将触发一个称为convert的Lambda,A)启动MediaConvert作业,B)将DynamoDB中的记录保存为conversionStatus = created且定义了streamUrl 。 MediaConvert将沿发送到SNS主题的方式触发多个事件。 名为...
  • 该插件可通过官方插件来源获得,因此只需启动Movian并转到“可用插件”菜单。 但是,如果您想手动安装插件,只需使用Movian“播放” zip文件,即可安装该文件。 如果您正在开发,则使用Movian的-p命令行参数以及...
  • 介绍 这是README文件,其中包含用于访问UNAVCO实时数据流并将已解析的数据上载到在线网络工具CHORDS的脚本套件的信息和说明。 您可以在此存储库中或从主要找到其他。... 根据parameter.json中的parameter.json启动UNA
  • 一个Raspberry Pi网站,可以在检测到运动时流式传输来自连接的摄像机的视频并记录监视视频。 这是 (瑞士)152号模块的学校项目。 注意:这是一个实践项目,决不打算或不适合用于严重的监视用例。 除其他严重的安全...
  • 第1步-启动服务器 java -jar essentialprogramming-http-video-streaming.jar 第2步-观看您喜欢的视频 打开浏览器,然后转到:localhost:8082 打开浏览器,然后转到:localhost:8082 / player.html :gem_stone:...
  • 它以空格键输入启动记录以开始,然后从 2 开始倒计时并开始记录。 它显示方形纵横比,并进行将文件保存为方形所需的后期记录修剪。 它将文件保存为 test_movie.mp4,并将文件保存到您的桌面。 音视频输入设备可...
  • 从Elasticsearch流式传输日志,可通过查询参数进行控制。 加载速度(比Kibana快得多),可以轻松生成查询。 查询示例: 有关完整的文档和示例,请参见 。 跑步 有几种方法可以运行es-stream-logs: docker-...
  • 一种跨平台的Java应用程序,用于使用软件定义无线电(SDR)解码,监视,记录和流式传输集群移动和相关无线电协议。 图1: sdrtrunk版本0.3.0应用程序屏幕截图 最终用户说明: 如果您只想下载并运行该程序,请按照...
  • StreamIt 这个iOS应用程式可将您的iOS装置变成串流相机。... 只需启动该应用程序,然后点击屏幕以显示您的流URL。 在Web浏览器中复制此URL即可。 请注意,这仅适用于本地网络(不适用于Internet)。
  • 这是我一直在做的实验开发的一小部分,它通过将音素数据解析为正则表达式,并同时以响应方式将其流式传输,从而将ASCII艺术与音频同步。 暴露这部分内容有些仓促,但我认为它应该显示一些创造性的问题解决方法。 ...
  • 在交互式监视模式下启动测试运行器。 有关更多信息,请参见关于的部分。 yarn build 构建生产到应用程序build文件夹。 它在生产模式下正确捆绑了React,并优化了构建以获得最佳性能。 生成被最小化,并且文件名...
  • 特别适用于将平滑的合成视频流式传输到Zoom,Hangouts,Jitsi等。类似于但适用于macOS。 这段代码是从,而本身是从。 已达到合并到核心OBS代码库中的目标 :crossed_fingers: 。 捐献 :money_with_wings: 考虑通过...
  • 此应用程序的目的是在发生这些事件时(在几分钟之内)从这些帐户中流式传输新推文,并获得浏览器通知。 这非常适合跟上可能在交易时影响加密资产价格的加密新闻。 用法 克隆此。 更改目录cd crypto-scanner 。 ...
  • 利用流式套接字传输数据文件

    千次阅读 2015-12-18 21:39:28
    服务器端: 1>建立一个基于对话框的应用程序Stream...3>双击“启动按钮”,添加以下代码,初始化网络,启动服务器监听void CStreamSocketServerDlg::OnOK() { // TODO: Add extra validation here WSADATA wsaData;

    服务器端:
    1>建立一个基于对话框的应用程序StreamSocketServer
    2>设计界面,将“确定”按钮的标题改为“启动”
    3>双击“启动按钮”,添加以下代码,初始化网络,启动服务器监听

    void CStreamSocketServerDlg::OnOK() 
    {
        // TODO: Add extra validation here
        WSADATA wsaData;
        /*
        typedef struct WSAData
        {
            WORD wVersion;  //为希望使用的Winsock版本
            WORD wHeighVersion;  //返回现有的Winsock库的最高版本
            char szDescription[WSADESCRIPTION_LEN+1];  //通常不用
            char szSystemStatus[WSASYS_STATUE_LEN+1];  //通常不用
            unsigned short iMaxSockets;  //可同时打开的套接字数
            unsigend short iMaxUdpDg;    //数据报最大长度
            char FAR * lpVendorInfo;   //为制定Winsock实施方案的厂商信息所预留,在任何一个Win32平
    
    台上都没有使用这个字段]
        }
        */
    
        //初始化TCP协议
        BOOL ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
        /*
        int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
        wVersionRequested 用户制定准备加载的Winsock库的版本.
        宏定义MAKEWOARD(X, Y) 获得wVersionRequested的正确值, [X为高位字节,Y为低位字节, 
        lpWSAData 为指向LPWSDATA结构的指针,包含了加载库版本有关的信息
        */
        if(ret != 0)
        {
            MessageBox("初始化网络协议失败!");
            return;
        }
    
        //创建服务器端套接字
        ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        /*
        SOCKET socket(int af, int type, int protocol);
        af用于制定网络类型,一般取AF_INET,表示该套接字在Internet域中进行通信
        type用于指定套接字类型,SOCK_STREAM表示流套接字, SOCK_DGRAM表示数据报套接字
        protocol用于指定网络协议,默认为0,表示TCP/IP协议
        */
        if(ServerSock == INVALID_SOCKET)
        {
            MessageBox("创建失败!");
            closesocket(ServerSock);   
        }
    
        //绑定到本地一个端口上
        sockaddr_in localaddr;
        /*
        struct sockaddr_in
        {
            short sin_family;   //必须为AF_INET,表示该socket处于Internet域
            u_short sin_port;   //用于指定服务端口
            struct in_addr sin_addr;  //把一个IP地址保存为一个4字节的数,其数据类型为无符号长整数
    
    类型
            char sin_zero[8];    //只充当填充项角色,使得与sockaddr长度保持一致
        }
        */
        localaddr.sin_family = AF_INET;
        localaddr.sin_port = htons(6000);  
        /*
        htons的功能:将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)
        参数u_short hostshort:16位无符号整数
        返回值:TCP/IP网络字节顺序.
        */
        localaddr.sin_addr.s_addr = 0;
        if(bind(ServerSock, (struct sockaddr *)&localaddr, sizeof(sockaddr)) == SOCKET_ERROR)
        {
            MessageBox("绑定地址失败!");
            closesocket(ServerSock);
            WSACleanup();
            return;
        }
        /*
        int bind(SOCKET s, const struct sockaddr FAR *name, int namelen);
        s标识一个未捆绑套接字的句柄,用来等待客户机的连接
        name是赋予套接字的地址
        */
    
        //将ServerSock设置为异步非阻塞模式,并为它注册各种网络异步事件 
        //m_hWnd为应用程序的主对话框或主窗口的句柄
        if(WSAAsyncSelect(ServerSock, m_hWnd, NETWORK_EVENT, FD_ACCEPT|FD_CLOSE|FD_READ|FD_WRITE) == 
    
    SOCKET_ERROR)
        {
            MessageBox("注册失败!");
            WSACleanup();
            return;
        }
        /*
        int WSAAsyncSelect(
            SOCKET s,    
            HWND hWnd,   //接收消息的窗口句柄
            unsigned int wMsg;  //网络事件发生时要接收的消息
            long lEvent;   //被注册的网络事件
        );
        lEvent参数值及意义:
        FD_READ  希望在套接字s收到数据时收到消息
        FD_WRITE 希望在套接字s可以发送数据时收到消息
        FD_ACCEPT 希望在套接字s收到连接请求是收到消息
        FD_CONNECT  希望在套接字s连接成功是收到消息
        FD_CLOSE 希望在套接字s连接关闭是收到消息
        FD_OOB 希望在套接字s收到外带数据时收到消息
    
        NETWORK_EVENT 为自定义消息,并添加其响应处理函数OnNetEvent(WPARAM wParam, LPRAM lParam)
         */
    
        listen(ServerSock, 31); //设置为侦听模式,最多要31个连接
        MessageBox("服务启动成功!");
        CDialog::OnOK();
    }

    4>注册自定义消息NETWORK_EVENT, 并添加其相应处理函数OnNetEvent
    这里写图片描述
    在StreamSocketServerDlg.h中添加成员函数:

    void OnNetEvent(WPARAM wParam, LPARAM lParam);

    在StreamSocketServerDlg.cpp中实现:

    void CStreamSocketServerDlg::OnNetEvent(WPARAM wParam, LPARAM lParam)
    {
        int iEvent = WSAGETSELECTEVENT(lParam); //调用Winsock API函数,得到网络事件类型
        SOCKET CurSock = (SOCKET)wParam;  //调用Winsock API函数,得到此事件的客户端套接字
        switch(iEvent)
        {
        case FD_ACCEPT:  //客户端连接请求事件
            TRACE("Get client call!\n");
            OnAccept(CurSock); 
            break;
        case FD_CLOSE:   //客户端断开事件
            OnClose(CurSock);
            break;
        case FD_READ:   //客户端网络包到达事件
            OnReceive(CurSock);
            break;
        case FD_WRITE:  //发送网络数据事件
            break;
        default: break;
        }
    }

    5>添加客户端的连接请求处理函数

    void CStreamSocketServerDlg::OnAccept(SOCKET CurSock)
    {
        SOCKET TempSock;
        struct socaaddr_in ConSocketAddr;
        int addrlen;
        addrlen = sizeof(ConSocketAddr);
        TempSock = accept(CurSock, (struct sockaddr*)&ConSocketAddr, &addrlen);
        /*
        用于接受连接请求
        SCOKET accept(
            SCOKET s,   //Socket的识别码
            struct sockaddr FAR * addr,  //存放连接的客户端地址
            int FAR* addrlen  //地址长度
        )
        */
        if(ConnectSock == INVALID_SOCKET)
            MessageBox("INVALID_SOCKET");
        TRACE("建立新连接,sock:%d\n", TempSock);  //输出调试信息
        inet_ntoa(ConSocketAddr.sin_addr);
        ConnectSock = TempSock;
        char *filename = "c:\\001.doc";
        if(!SendFile(filename, ConnectSock))
            MessageBox("发送失败!");
    
    }

    6>添加发送数据文件函数

    BOOL CStreamSocketServerDlg::SendFile(char *name, SOCKET conn)
    {
        char *FileName = name;
        SOCKET TcpConn = conn;
        CFile file;
        if(!file.Open(FileName, CFile::modeRead))
        {
            printf("打开%s失败!\n", FileName);
            return FALSE;
        }
        int NumBytes;  //用来保存每次传送时数据块的大小
        UINT Total = 0;  //用来保存套接字已经传送的总的字节数
        int BufSize = 1024;  //发送缓冲区的大小
        int Size = BufSize;  //读取文件的大小
        LPBYTE pBuf = new BYTE[BufSize];  //发送缓冲区
        DWORD dwTemp = 0;
        UINT FileLength = file.GetLength();  //得到文件的大小并发送出去
        send(TcpConn, (char *)&FileLength, 4, 0);
        /*
        int send(  //返回发送的字符总数
            SOCKET s,
            const char FAR *buf,  //存放要传送的资料的暂存区
            int len,  //buf的长度
            int flags   //此函数被调用的方式
        )
        */
        file.SeekToBegin();
        while(Total < FileLength)
        {
            if((int)(FileLength - Total) < Size)
                Size = FileLength - Total;
            Size = file.Read(pBuf, Size);
            /*
            virtual UINT Read(
                void* lpBuf,  //是把资源读入哪里
                UINT nCount   //是读入的字节数
            );
            */
            NumBytes = send(TcpConn, (char *)pBuf, Size, 0);
            if(NumBytes == SOCKET_ERROR)
            {
                send(TcpConn, "ERROR", sizeof("ERROR")+1, 0);
                return FALSE;
            }
            Total += NumBytes;
            file.Seek(Total, CFile::begin);
        }
        delete[] pBuf;
        file.Close();
        closesocket(TcpConn);
        return TRUE;
    }

    客户端:
    1>新建一个基于对话框的程序StreamSocketClient
    2>设计界面,添加编辑框m_CtrlPAddress输入IP地址,m_iPort用于输入端口,将“确定”按钮改为“连接”,“取消”改为“关闭”
    3>双击“连接”,添加以下代码:

    void CStreamSocketClientDlg::OnOK() 
    {
        // TODO: Add extra validation here
        UpdateData(FALSE);  //初始化对话框中的数据
        WORD wVersionRequested;
        WSADATA wsaData;
        int err;
        wVersionRequested = MAKEWORD(2, 2);  //连接两个给定的无符号参数
        err = WSAStartUp(wVersionReqested, &wsaData);
        if(err != 0)
            return;
        if(LOBYTE(wsaData.wVersion) != 1) || HIBYTE(wsaData.wVersion) != 1) //LOBYTE()得到一个16bit数
    
    最低(最右边)那个字节
        {
            WSACleanup();
            return;
        }
        SOCKET TcpClient = socket(AF_INET, SOCK_STREAM, 0);
        SOCKADDR_IN SerAddr;
        SerAddr.sin_family AF_INET;
        SerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
        /*
        struct in_addr{
            union{
                struct{ u_char s_b1, s_b2, s_b3, s_b4;} S_un_b;
                struct{u_short S_w1, S_w2} S_un_w;
                u_long S_addr;
            }S_un;
        };
        */
        SerAddr.sin_port = htos(m_iPort);
        connect(TcpClient, (SOCKADDR*)&SerAddr, sizeof(SerAddr));  //与服务器端建立连接
        /*
        int connect(
            SOCKET s,  //服务器端Socket的识别码
            const struct sockaddr FAR* name,  //Socket想要连接的对方地址
            int namelen  //地址长度
        )
        */
        long FileLength;
        recv(TcpClient, (char *)&FileLength, sizeof(long), 0);
        /*
        int recv(
            SOCKET s,   
            char FAR *buf,   //存放接收到资料的暂存区
            int len,    //buf的长度
            int flags   //此函数的调用方式
        )
        */
        if(RecvFile("c:\\003.doc", TcpClient, FileLength))
            MessageBox("传输结束!\n");
        else
            MessageBox("传输失败!\n");
        CDialog::OnOK();
    }

    4>添加接收文件函数

    BOOL CStreamSocketClientDlg::RecvFile(char *name, SOCKET conn, UINT filelen)
    {
        char *FileName = name;
        SOCKET client = conn;
        CFile file;
        if(!file.Open(FileName, CFile::modeWrite))
        {
            printf("打开%s失败!\n", FileName);
            return FALSE;
        }
        int NumBytes;  //用来保存每次接收时数据块的大小
        UINT Total = 0;  //用来保存套接字已经接收的总的字节数
        int BufSize = 1024;  //接收缓冲区的大小
        int Size = BufSize;  //写文件的大小
        LPBYTE pBuf = new BYTE[BufSize];  //接收缓冲区
        DWORD dwTemp = 0;
        file.SeekToBegin();
        while(Total < filelen)
        {
            if((int)(filelen - Total) < Size)
                Size = filelen - Total;
            NumBytes = recv(client, (char *)pBuf, Size, 0);
    
            if(NumBytes == SOCKET_ERROR)
            {
                printf("接收失败!\n");
                return FALSE;
            }
            file.Write(pBuf, NumBytes);  
            /*
            virtual void Write(  
                const void* lpBuf,   //存储要写的东西的字符串或者字符数组
                UINT nCount );   //要从这个字符串或者字符数组中写多少个字符到文件中
            */
            Total += NumBytes;
            file.Seek(Total, CFile::begin);
        }
        delete[] pBuf;
        file.Close();
        closesocket(client);
        return TRUE;
    }

    界面:
    这里写图片描述

    这里写图片描述

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 213
精华内容 85
关键字:

启动流式传输