如何实现传文件?

larryuan 2000-08-08 11:34:00
用socket,udp之类的东西如何实现传文件?
我有许多地方搞不清,比如怎样判断文件的起点和终点;
如何让双方保持同步,双方的确认协议是怎样的等等。
希望高手指点,最好举个例子,谢!
...全文
327 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
PoolD 2000-08-10
  • 打赏
  • 举报
回复
to larryuan:
>ServerSocket.Socket.Connections是指与当前各个客户端的连接,我是说比如某一个
>客户端向服务器在发一个文件的同时又发了一个消息,会冲突吗?
说实在的,这个问题我考虑过,但是如果是自己做的客户端,这个问题是可以绕过去的。只要你在写程序的时候避免这种可能性就行了。

其实我个人认为第二种方法是比较好的。其实你说的问题解决起来并不麻烦,因为你可以在传送的CMD中夹带文件的长度信息。
关于1.可以用Socket的Handle或者Addr判断是从哪里传送的信息。
关于3.A.packed的作用是压缩record所占用的内存空间(我的理解)
B.根据我的经验,这样的结构占用的内存空间是以最大的为准(8 + 1024 byte)。如果你用netdata.msg,取出的就是前128byte,如果是netdata.file,取出的就是整个1024byte。可能表达的不是很清楚。
区分integer的值可以这样定义:
netdata = record
cmd : array[0..7] of byte;
case packagetype: integer of
1: (msg : array[0..127] of byte);
2: (file : array[0..1023] of byte);
end;
C.好像是不可以的。
D.是。
E.可以。
ckbmail 2000-08-10
  • 打赏
  • 举报
回复
我认为是这样的
larryuan 2000-08-10
  • 打赏
  • 举报
回复
to PoolD:
ServerSocket.Socket.Connections是指与当前各个客户端的连接,我是说比如某一个
客户端向服务器在发一个文件的同时又发了一个消息,会冲突吗?
你说的协议方法我也考虑过:
1。我觉得这样会更不同步,比如一个客户端A向服务器发送文件,同时另一个客户端B
向服务器发送消息,服务器先接到了A的请求,又接到了B的请求,准备用数据socket
先接收A的文件,但由于网络岩石B的消息先到达,这不就接错媳妇了吗。
2。我现在考虑的是用这种方法,但还是不太清楚,比如先收到特定的cmd表示文件开始,
总要有cmd表示文件结束吧,但如果文件内容中正有这样的字,就中断了文件的传输了。
3。我以前考虑用这个方法,但由于以下的语法问题(嘿嘿,惭愧)放弃这种方法:
A。定义record中packed的作用是什么?
B。在Record中用case ... of语句做到不定的数据类型,如区分文件或消息,和你想
差不多:
netdata = record
cmd : array[0..7] of byte;
case integer of
1: (msg : array[0..127] of byte)
2: (file : array[0..1023] of byte);
定义我知道,但如何使用它呢,就是怎么区分integer的值?
C。由于文件的大小是不定的,在record中可以使用不定大小的数据类型吗?
D。record的大小是不是等于它最大可能的大小?如果是,那么我要是传一个几字节的
小消息结果却相当与传了一个文件?(这点可能是我概念糊涂)
E。用socket的sendbuf可以直接传record吗?还是要转化一下?我用ReceiveBuf接不
到传来的record。

sorry,我问的是不是太多了?好象分值不只100分,可我就剩这100分了,呵呵。
larryuan 2000-08-10
  • 打赏
  • 举报
回复
to mophy:
thank u, i have find it.
larryuan 2000-08-10
  • 打赏
  • 举报
回复
to poold:
en,谢谢你的回复。
就这样吧,以后再遇到什么问题,再请教,OK?
PoolD 2000-08-10
  • 打赏
  • 举报
回复
>继续1
可以建立一个数组,用于临时存放这些信息。
>继续2
既然可以判断来源,当然不会混起来,自己处理一下就好了。
>另外Socket和UDP构件一次传输数据包的最大限度是不是8K?
这个我不是很清楚,因为我一般都不会用到很大的包。
larryuan 2000-08-10
  • 打赏
  • 举报
回复
to PoolD:
由于C和D的原因,我还是决定放弃3。不过我还是在问问B:
你的意思是说,在赋netdata.msg or netdata.file前,要先赋netdata.packagetype=1 or 2
在使用的时候,检查netdata.packagetype的值来判断用netdata.msg还是netdata.file
不知道我理解的对吗?
继续1。通过socket.remoteaddress可以判断出数据是来自B的,但如何处理它呢?把它丢掉,
还是先临时存起来?
继续2。虽然可以加入文件长度信息,还是无法避免开始说的那个问题,比如服务器正接收
来自A的文件,此时B发来一个5K的消息,它掺在A的文件中,那么A的文件就少了后5K的内容了。

另外Socket和UDP构件一次传输数据包的最大限度是不是8K?这是构件本身规定的还是TCP/IP
协议规定的?
mophy 2000-08-09
  • 打赏
  • 举报
回复
有这样的例子:

http://go.163.com/~lovejingtao/
larryuan 2000-08-09
  • 打赏
  • 举报
回复
to mophy:
有不少好东西,可没找到我要的呀。
mophy 2000-08-09
  • 打赏
  • 举报
回复
to larryuan:
呵呵,你没有仔细找吧: http://go.163.com/~lovejingtao/TcpIpSend.zip
这不就是吗? :-)
PoolD 2000-08-09
  • 打赏
  • 举报
回复
ServerSocket在与每个ClientSocket建立联接的时候都产生一个独立的Socket
(ServerSocket.Socket.Connections[X]),所以不会有冲突。
至于确认协议,你可以自己定义一个简单的协议。比如什么信息代表请求文件,什么信息代表开始发送等。
命令字与实际文件内容的区分可以用三种方法:
1. 用两对Socket分别传送命令字与数据。
2. 定义一个特定的串(如$68493874),如果当前没有数据的传送,那么收到这个串之后的信息就被认为是命令。具体的协议方式可以参考一下打印机或者Modem的数据传送。
3. 定义一个结构,比如:
netdata = record
cmd : array[0..7] of byte;
info : array[0..127] of byte;
data : array[0..1023] of byte;
end;
双方通过结构中的cmd判断命令,info判断文件位置等,data是文件内容。
SendBuf的时候发送这个结构。
larryuan 2000-08-09
  • 打赏
  • 举报
回复
to poold:
我没试过,不知你用这个方法做过传文件吗,我想可能会有些问题,
如果在传一个大文件,那么socket or udp收到其它消息或文件会不会冲突?
如果分成包,正如我上面问的如何判断文件的起点终点和各包的起点终点,
以及确认协议。
我说的确认协议不是TCP,UDP的协议,而是如何判断收到的是文件,文件已经
传完,回复确认信息等等。这些应该都是命令字吧,还有如何区分命令字与
实际的文件内容。
如果你做过,能给我一份例子看看吗?
PoolD 2000-08-09
  • 打赏
  • 举报
回复
大文件也是可以的。可以用SendBuf将大文件分块传送,只要加上适当的位置控制就可以了。
larryuan 2000-08-08
  • 打赏
  • 举报
回复
我用的就是这个,还有UDP控件,不过要是传个大文件比如几M,
直接用就不行了吧。
PoolD 2000-08-08
  • 打赏
  • 举报
回复
可以使用Delphi提供的TServerSocket和TClientSocket控件。
在ServerSocket设定端口号监听,在ClientSocket设定Server地址和端口号后即可方便的建立联接。
建立连接之后可以使用它们的Socket属性中的SendBuf、SendText和SendStream等过程实现文件传输。
至于同步等问题可以不必考虑。

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧