文件传送与SOCKET有关问题!(得到答案就马上给分!)
文件传送与SOCKET问题!(得到答案就马上给分!)
想做一个一对一聊天的程序,程序可以在聊天时也能发送文件,还能进行语音和视频,但是有几个问题不太明白。
一)以前我做过单一的聊天程序,用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来做,两者做得话会有什么区别?
希望高手们能给我上面三个问题给点建议,(如果你能解答其中一个那也请帮忙解答)最后再能给一个整体性的建议和指导思想,怎么样完成一样聊天,文件传送或语音视频同步进行的程序?谢谢!
------解决方案--------------------
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都是完全可以。单纯的文件传输都可以这么做
------解决方案--------------------
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的主机来建立两不同局域网主机之间的连接。当然,同一个局域网内的主机就不存在这个问题,所以我问你想做到怎样的一个层次人。)
想做一个一对一聊天的程序,程序可以在聊天时也能发送文件,还能进行语音和视频,但是有几个问题不太明白。
一)以前我做过单一的聊天程序,用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来做,两者做得话会有什么区别?
希望高手们能给我上面三个问题给点建议,(如果你能解答其中一个那也请帮忙解答)最后再能给一个整体性的建议和指导思想,怎么样完成一样聊天,文件传送或语音视频同步进行的程序?谢谢!
------解决方案--------------------
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都是完全可以。单纯的文件传输都可以这么做
------解决方案--------------------
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的主机来建立两不同局域网主机之间的连接。当然,同一个局域网内的主机就不存在这个问题,所以我问你想做到怎样的一个层次人。)