您的位置:程序门 -> vc/mfc -> 网络编程



文件传送与socket问题!(得到答案就马上给分!)


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


文件传送与socket问题!(得到答案就马上给分!)[已结贴,结贴人:ds117]
发表于:2007-04-15 21:22:16 楼主
想做一个一对一聊天的程序,程序可以在聊天时也能发送文件,还能进行语音和视频,但是有几个问题不太明白。

          一)以前我做过单一的聊天程序,用winsokcet实现,感觉很简单。比如我要发送一   句“你好!”给对方,直接用send函数就可以传送过去,send函数原形:send(socket   s,const   char   far   *buf,   int   len,int   flags);在这里,我只要把字符串付给第二个参数buf就行了!而我现在要传送的是一个文件,比如说一个电影文件,怎么传?这可是个电影文件,又不是字符串如“你好!”一样,总不能直接把它付给buf参数传过去吧。

          二)如果我在程序里面创建了一个sock,并bind定一个ip主机地址,现在我用这个sock进行聊天时的数据发送和接收,可在这个时候,我又要传送文件了,这两者要并行进行,那怎么办?难道这个sock可以同进行聊天时的数据发送与接收又同时进行文件的接收或发送吗?根据我的理解应该不可能,因为我想如果同一个sock它可能没法区别到里是电影文件还是聊天的数据文件接收到了。如果这样的话,那么我们就创建两个sock,可是问题又来了,因为两个sock是不能同时邦定到同一个ip地址的。如果这样,那我怎么样处理sock才能同时进行聊天和文件传送呢!

          三)我刚刚在网上查了一下有关文件传送的资料,但是不多,有网友说比如传送电影这样的大文件,必需把文件分开来传送,而不能一次性就把它传送过去?为什么不能一次性传过去呢?如果要分开来传,在接收端又怎么样组合起来呢,如果分开传的话,我们应该选择tcp的sock来做,还是应该用udp来做,两者做得话会有什么区别?

希望高手们能给我上面三个问题给点建议,(如果你能解答其中一个那也请帮忙解答)最后再能给一个整体性的建议和指导思想,怎么样完成一样聊天,文件传送或语音视频同步进行的程序?谢谢!
发表于:2007-04-15 21:48:031楼 得分:30
1.const   char   far   *buf   这个参数可以用缓冲区的指针,指向电影文件缓冲区。在计算长度的时候,不能用strlen,而应该用文件长度,或者缓冲区长度

2。bind的socket只用来接受客户端连接,accept返回的新socket采用来聊天通信,传送文件的时候想同时聊天,最好由客户端从新发起一个socket,connect,服务端使用这个新的socket来处理文件通信,服务端虽然使用了同一个端口通信,但是可以通过不同socket句柄来区分什么样的数据

3。一次性传送数百m的数据,不是不可以,重叠io或者iocp就行,但是请求send这么多,并不代表底层缓冲可以一次处理这么多,大多数情况下,完成通知会告诉你这次完成的字节数,你需要继续投递wsasend来投递剩下的字节数

send端投递10个1m字节,但是recv端则可以一次投递接受10m的请求,send10m,recv10次1m都是完全可以。单纯的文件传输都可以这么做
发表于:2007-04-15 21:49:432楼 得分:0
传送大文件当然是要另外再建立一条连接的,另外开一个线程,循环从文件里read一块数据,send一块数据,直到传送完毕。
“两个sock是不能同时邦定到同一个ip地址”,这个是明显没有学好socket编程,再去好好翻翻书。
其实可以有更简单的解决方案,比方说在你的服务器上开一个ftp或者http服务,发个url给客户端自己去下载就结了。
发表于:2007-04-15 22:33:023楼 得分:0
自己约定好传送文件,聊天,视频,语音的协议就行了
发表于:2007-04-15 23:10:374楼 得分:0
我正在做一个仿bt的文件传输系统,所以你的问题听我的答案吧。我会解除你所有疑惑。呵呵。

一)文件是存放在硬盘上的,而你使用docket发送文件时是使用缓冲区将数据发送出去。所以要发送文件只要把文件读到一个缓冲区中,就可以像发送字符串一样的发送文件了。当然文件在另一客户端还要从缓冲区写入硬盘。

二)既要传文件又要传送聊天信息。理论上绝对可以,但是我们一般不会这样做,至于为什么,我一会告诉你。你比较有预见性的提出了如何分辨传送过来的信息的类别问题。这就要在你传送的信息中加入标识。比如:你传送一个结构如下:
typedef   struct   tagheader
{
int   type;
byte[1024];
}header,*pheader;
在接收端将接收到的缓冲区内容转换为header类型,判别type的类型,如果type=0;那么就是传送的文件,如果type==1就是传送的聊天内容。等等type==2   ,语音     之类。当然,传送方和接收方要一致,不要出现传送方发文件给type赋值为0,而在接收方却将type==1的情况当成文件来处理。
上面是识别问题。我再说下为什么不这样用,因这在同时传送文件和聊天信息及语音等多种情况时,可能出现延时的情况,在线程级别上即是可能出现发送聊天信息的时候,系统一直在处理传送文件的工作。这种情况会导致相当量的操作得不到及时的处理(在这里是不及时的发送出去),这就在一些对时间及速度要求高的地方如语音,不能很好的满足功能需求,故而不用。
关于能否创建两个socket   。你的担心是多余的。作为服务器的一方,和ip绑定的socket只用于socket接收连接,应该创建新的socket来和作为接收到socket的连接对象。

三)文件一般不会一次传输完全,不是别的原因。因为所有的文件在传输的时候首先在读到一个缓冲区中。试想一台并能电脑配置是512m内存,而一个文件过大比如300m。这样在系统进程需要一定的内存,及一些其他的程序。最少在消耗120m以上的内存,这样你要一次性申请一个大的连续缓冲区(这里是300m)在绝大时候是不可能成功的。文件分块传输就是为了解决这个问题。(另外还解决一个网络传输中分片传输,之后重组碎片的情况,这里你不需要了解。)
发表于:2007-04-15 23:13:285楼 得分:0
关于tcp还是udp的问题,你告诉我你想做到一个怎样的层次。如果和商用一样的层次,恐怕要用udp。这牵涉到一个相当有水准的问题。不是三言可以说清楚。不过我可以指条路。

内网穿透问题。
发表于:2007-04-16 00:48:006楼 得分:0
谢谢:
vieri_ch(尘雨-自在飞花轻似梦,无边丝雨细如愁)  
特别谢谢:
minger909(惜之)  

        你们解说的非常常好,心里面对一些问题清楚多了,不过我还没能理解是否能同时创建多个sock,因为我在一本书上看到这么一句话:两个不同的套节字不能绑定到相同的本地地址去监听到来的连接;到目前还没有想到用一个比较好的方法实现对聊天,和文件并发进行方案,不过minger909(惜之)   方法很不错,我曾经也想过,可是我怕的就是文件在传送时,不能同步,比方说:服务器第一次传1m数据过来,客户接收,可是当服务器传第二次1m数据过来时,而客户端却还在接收处理第一次的1m数据,这时会不会造成第二次传来的数据丢失呢。还有我在后面问到的是用基于tcp还是udp的问题上,我为什么要考虑这个问题呢,因为udp是面向无联接的,数据容易丢失,而这种情况对传送文件来说是致名的,因为一但文件有一个块没有被接收到的话,那么整个传过来的文件将是错误打不开的。
        所以以上还有这么多疑问,我希望有人再能给我指点指点。不过你们俩的分我先记着了,等结贴时一定给你们!谢谢了!
发表于:2007-04-16 08:43:367楼 得分:0
文件,消息可以用同一个socket传输,只要通信之前收发双方约定一个协议,让接收方知道什么时候是文件,什么时候是消息就行了。
对于文件传输,你可以分节进行,比如说以4k为一个发单位,循环进行,这样多大的文件都一样可以传到接收方。
当然,要保证可靠传输,你在协议里还可以加上接收完成标志,请求重发标志等等。
发表于:2007-04-16 08:59:188楼 得分:0
udp有一个问题,就是包序的问题,这个可以在发送端封包的时候增加包序号来解决,接受端接收之后按照包序号来组包,如果某一个序号的包丢失或者不完整,那么可以让通知发送端重发,这在udp处理是很常见的
tcp是可靠的面向连接方式的。包序也是有保障。
有两种处理方式
1,iocp模型这样做,发送端一次提交wsasend发送所有数据,在完成通知工作线程里面依次提交wsasend剩下的数据。虽然所有的数据都是分次发送了,但是能保证在网络层上有序的传输。在接受端,iocp模型可以一次提交wsarecv接受这个文件长度的数据,在完成通知工作线程里保存并处理已经接收到的,并提交wsarecv继续接受剩下的数据。这样的方式可以充分发挥iocp的特点,包数据确保有序和基本完整(某种程度上的完整)。接受端获取文件长度以及相关信息则可以由发送端在发送文件前与接受端协商一个数据。先发一个文件信息封包。告诉接受端,提交发送的文件到底有多大。iocp模式下不用把文件分成多个wsasend,同时提交,虽然可以这样做,但实际上并不需要,否则处理的逻辑会复杂,对于效率是一个影响

2.可以在发送端把文件分包,提交非堵塞wsasend,这样做必须再分包之后,给每个包加包头记录该包的大小和序号,如果需要可以加上校验和,这些包发出的顺序可以任意。接受端收到各个包之后,按照序号组包校验,如果缺包或者坏包,放弃数据,并通知发送端重新提交该包。直至所有的包都收到并校验组包成功。
这种方式需要两端协商一个重发协议,好处是在网络状况不好的情况下,尽可能的保障数据完整,使用逻辑方式确保序列正确。但是也有效率稍低等问题。

与bind这个操作相关的socket,可以说与收发数据没有直接关系,其实这个socket作用在于,承担处理连接请求,当然同时只能一个socket绑定一个ip:port。

聊天和文件并发的方案你可以放弃了。即便是现在的主流im,基本上都是分开的,原理上,就是在同一个socket你可以收发任何你想要的数据,但是一个socket上处理的协议数据包过多,你的服务端和客户端的复杂度越高,越不稳定,而且效率很低。文件传输本身就是又要效率又要完整的需求,夹杂着聊天和数据传输的流数据会让你无所适从。不如另辟socket传输,用完即释放
发表于:2007-04-16 09:10:269楼 得分:0
服务端用于数据收发的socket通常来自于accept返回的那个socket,所以并非你自己去创建,当然也可以服务端创建新的socket发起connect请求客户端,在这个socket上进行专门收发。不过客户端和服务端都成了混合型。
发表于:2007-04-16 10:39:5710楼 得分:30
1)不过我还没能理解是否能同时创建多个sock,因为我在一本书上看到这么一句话:两个不同的套节字不能绑定到相同的本地地址去监听到来的连接;到目前还没有想到用一个比较好的方法实现对聊天,和文件并发进行方案
---
两个不同的套节字不能绑定到相同的本地地址去监听到来的连接;这个对初学者或是一般的socket使用是绝对正确的。(注意上面的“本地地址”是指ip+端口,端口不同的相同ip是绝对可以绑定到不同的套接字上的。)
(不过在一些高难度的编程中经常会使用到端口复用这个技术,可以使得同一ip+端口   对应不同的套接字。这里你也不需要了解。)
再来,你并不需要创建多个socket用于监听,而只需要一个。在监听到连接时就创建一个新的套接字用于连接监听到的套接字。这个是基础,可能你有点混了。这样可以实现不同的socket处理不同的任务(对应文件,聊天,语音)。但是完成的socket类要负责处理所有的这些任务,根据我所说的标识方法。只是你的不同套接字只用来接收不同的任务,只会调用对应标识中的代码。
你仔细想下上面这点话,不要迷糊了。

怕的就是文件在传送时,不能同步,比方说:服务器第一次传1m数据过来,客户接收,可是当服务器传第二次1m数据过来时,而客户端却还在接收处理第一次的1m数据,这时会不会造成第二次传来的数据丢失呢。
---
这个担心是多余的。只要发送过来的数据,系统会自动放在缓冲区中等待你的处理(这里对就消息的方式存在),不会丢失。当处理到对应数据时,即处理系统对应消息,系统会调用缓冲区中的数据,供你使用。

还有我在后面问到的是用基于tcp还是udp的问题上,我为什么要考虑这个问题呢,因为udp是面向无联接的,数据容易丢失,而这种情况对传送文件来说是致名的,因为一但文件有一个块没有被接收到的话,那么整个传过来的文件将是错误打不开的。
---
我只能再夸你一次了   ,你很好学,想的很全面。
以你的功能要求来说,用tcp吧。为什么,你自己也是了解的。如果使用udp的话就要自己处理包数据   顺序错误,丢失的情况,这个也是要仿tcp协议的处理方式来做的,对你来说是相当有难度的。不过网上的p2p系统多是基于udp的,这牵涉到内网用户不可以做服务器这样一个弊端。
试想一下你如何向另外一个局域网内的主机发送连接呢。(你只知道它的外网ip,端口对应的是主机的而并不是网关的。网关会自动丢弃你的数据包,因为在它的记录中并不存在和你的ip   port之间的对应通信。亦,所的的连接的服务端都是拥有外网ip的主机,你只可以通过这个外网ip的主机来建立两不同局域网主机之间的连接。当然,同一个局域网内的主机就不存在这个问题,所以我问你想做到怎样的一个层次人。)


发表于:2007-04-16 13:04:3711楼 得分:0
1.   你要制定一个通信协议。   指定传输的内容类型:比如聊天,文件,其它控制等
2.   你设计的应该是   p2p   形式,   考虑到内网络,   你应该   用udp   ,然后打洞   穿透。
3.   关于视频文件,你应该分块,传输,每块建议1400以下。
发表于:2007-04-16 15:36:0912楼 得分:0
开多线程解决并发问题  
        文件传送用tcp协议
发表于:2007-04-17 00:40:3313楼 得分:0
再次谢谢:
vieri_ch(尘雨-自在飞花轻似梦,无边丝雨细如愁)  
特别谢谢:
minger909(惜之)  

本次先结贴给分,如还有不懂的再请教两位其其它的高手们!


快速检索

最新资讯
热门点击