小弟在公司维护一套VOD系统的上层软件,在工作中遇到困难想麻烦大家指点一下客户端是一套VOD终端,由上面的单片机完成工作.PC被当做VOD服务器使用服务端程序就是我想请求解决的问题.我是第一次写 多线程 + SOCKET 程序,希望阁下能把实现原理说详细一些.最好能给出一段示范代码
VOD工作原理
VOD终端启动以后,会向一个指定的IP地址(电脑主机)发送消息
主机收到消息后,就发一个消息给VOD终端(此时跟VOD连接的电视就出现节目菜单选择)
然后用遥控器对着VOD进行点播,VOD收到遥控器的按键信息后,再把按键信息发给主机,
主机上的程序,根据按键的不同取值,执行相应的的功能
相应的功能,分菜单选择,开始点播,停止点播等等
点播节目的时候,VOD终端会向主机发出要包信息,主机就会把多媒体信息传送给VOD终端,此时就会播放选择的节目了. VOD终端是公司自己开发的,里面的单片机程序和上层软件是搭配起来用的.我只知道把相应的消息发送给VOD终端后,VOD终端会根据主机发来的消息自动处理数据 上层软件主要涉及文件操作和SOCKET(SOCKET用来发送信息包用),还有一些写好的低层函数(用来向VOD终端发送命令).PS: 开发环境: winXP + delphi6.0 + 交换机 + 电视 + 一套VOD终端服务端程序介绍:
服务端程序由2个TNMUDP控件完成应答
一个UDP(cmdudp)用来和VOD进行应答过程,另外一个(vodudp)用来向VOD发送控制单片机的信息
2个UPD控件均指定好了固定端口
原来的程序里面,在 cmdudp.UDPDataReceived 过程里面实现应答过程
现在我不能使用 cmdudp.UDPDataReceived 过程,而改用线程处理
线程需要把 cmdudp.UDPDataReceived 的功能实现,而原来的udp.UDPDataReceived 过程就不再处理应答过程了我的理解:
1.在线程单元的create里面,动态创建2个UDP控件
2.原先的 udp.UDPDataReceived 过程实时向线程传送 IP,Numberbytes和port这3个参数
3.在线程单元内,写一自定义函数(过程?),用来实现 udp.UDPDataReceived 的功能
线程功能如下:
如果VOD没有向PC发信息,线程处于循环状态
一旦PC接收到信息,就在线程内实现udp.UDPDataReceived的功能
4.每个线程处理一个VOD终端.VOD终端启动后自动增加一个线程;VOD终端断电后,自动撤消相应的线程我的问题:
1.线程里面无法使用事件,请教如何写自定义函数(过程?),实现 udp.UDPDataReceived 过程的功能
2.如果不用UDP控件,可以用 UDPSOCKET控件实现吗?
3.可以用serversocket控件实现吗?
4.还可以用其他什么控件实现?(最好基于UDP协议)
5.我对 多线程 + SOCKET 有太多的细节不了解方便的话,请给出一段示范代码.
老程序的udp的ondatareceive事件如下:procedure TFORM1.CMDUDPDataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);var
x,ipadd,key,aindex:integer;
tempbuf:array [0..100] of char;
vcdb2:array [0..1177] of char;
lost_bag_ppp:integer; //丢失的包应该在的位置
//如果大于0,在new 缓冲中
//如果小于0,在old 缓冲中
temp_pointer:pchar;
//读数据的方式,根据要求的IP地址开辟缓冲区50*1176两个
//当第一个缓冲数据发完后数据转入备用缓冲
t,count:word;
BBBUF_SIZE:INTEGER;
back_pos:longint;begin if not can_send then //这里的 can_send可以不管它
exit;
//和本机地址相同的 IP应该退出
//dsp系统收到为0的数据包会停止发包,直到收到1的包才开始工作
ipadd:= checkfromip(fromip); //checkfromip是自定义函数,可以得到IP地址的最后一个数字 if ipadd = 0 then
exit; cmdudp.ReadBuffer(tempbuf, NumberBytes);
//收到了要包申请时应该判断
//首先应该判断CALL_FLAG的类型
BBBUF_SIZE:=BUF_SIZE*1176;
lost_bag_ppp:=100;//100是个超出范围的数,表示不是都的包,不使用
x:=byte(tempbuf[2]);
case x of
{这里开始对VOD传来的应答信息进行解析,详细过程省略}
else
exit; //如果不是以上的键,就应该退出
end; //end case {这里开始是公司的内部资料,主要是文件操作.以下省略}
end;
VOD工作原理
VOD终端启动以后,会向一个指定的IP地址(电脑主机)发送消息
主机收到消息后,就发一个消息给VOD终端(此时跟VOD连接的电视就出现节目菜单选择)
然后用遥控器对着VOD进行点播,VOD收到遥控器的按键信息后,再把按键信息发给主机,
主机上的程序,根据按键的不同取值,执行相应的的功能
相应的功能,分菜单选择,开始点播,停止点播等等
点播节目的时候,VOD终端会向主机发出要包信息,主机就会把多媒体信息传送给VOD终端,此时就会播放选择的节目了. VOD终端是公司自己开发的,里面的单片机程序和上层软件是搭配起来用的.我只知道把相应的消息发送给VOD终端后,VOD终端会根据主机发来的消息自动处理数据 上层软件主要涉及文件操作和SOCKET(SOCKET用来发送信息包用),还有一些写好的低层函数(用来向VOD终端发送命令).PS: 开发环境: winXP + delphi6.0 + 交换机 + 电视 + 一套VOD终端服务端程序介绍:
服务端程序由2个TNMUDP控件完成应答
一个UDP(cmdudp)用来和VOD进行应答过程,另外一个(vodudp)用来向VOD发送控制单片机的信息
2个UPD控件均指定好了固定端口
原来的程序里面,在 cmdudp.UDPDataReceived 过程里面实现应答过程
现在我不能使用 cmdudp.UDPDataReceived 过程,而改用线程处理
线程需要把 cmdudp.UDPDataReceived 的功能实现,而原来的udp.UDPDataReceived 过程就不再处理应答过程了我的理解:
1.在线程单元的create里面,动态创建2个UDP控件
2.原先的 udp.UDPDataReceived 过程实时向线程传送 IP,Numberbytes和port这3个参数
3.在线程单元内,写一自定义函数(过程?),用来实现 udp.UDPDataReceived 的功能
线程功能如下:
如果VOD没有向PC发信息,线程处于循环状态
一旦PC接收到信息,就在线程内实现udp.UDPDataReceived的功能
4.每个线程处理一个VOD终端.VOD终端启动后自动增加一个线程;VOD终端断电后,自动撤消相应的线程我的问题:
1.线程里面无法使用事件,请教如何写自定义函数(过程?),实现 udp.UDPDataReceived 过程的功能
2.如果不用UDP控件,可以用 UDPSOCKET控件实现吗?
3.可以用serversocket控件实现吗?
4.还可以用其他什么控件实现?(最好基于UDP协议)
5.我对 多线程 + SOCKET 有太多的细节不了解方便的话,请给出一段示范代码.
老程序的udp的ondatareceive事件如下:procedure TFORM1.CMDUDPDataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);var
x,ipadd,key,aindex:integer;
tempbuf:array [0..100] of char;
vcdb2:array [0..1177] of char;
lost_bag_ppp:integer; //丢失的包应该在的位置
//如果大于0,在new 缓冲中
//如果小于0,在old 缓冲中
temp_pointer:pchar;
//读数据的方式,根据要求的IP地址开辟缓冲区50*1176两个
//当第一个缓冲数据发完后数据转入备用缓冲
t,count:word;
BBBUF_SIZE:INTEGER;
back_pos:longint;begin if not can_send then //这里的 can_send可以不管它
exit;
//和本机地址相同的 IP应该退出
//dsp系统收到为0的数据包会停止发包,直到收到1的包才开始工作
ipadd:= checkfromip(fromip); //checkfromip是自定义函数,可以得到IP地址的最后一个数字 if ipadd = 0 then
exit; cmdudp.ReadBuffer(tempbuf, NumberBytes);
//收到了要包申请时应该判断
//首先应该判断CALL_FLAG的类型
BBBUF_SIZE:=BUF_SIZE*1176;
lost_bag_ppp:=100;//100是个超出范围的数,表示不是都的包,不使用
x:=byte(tempbuf[2]);
case x of
{这里开始对VOD传来的应答信息进行解析,详细过程省略}
else
exit; //如果不是以上的键,就应该退出
end; //end case {这里开始是公司的内部资料,主要是文件操作.以下省略}
end;
解决方案 »
- 文本文件的问题,各位请进
- FaseReport中Memo框中如果我写了代码,用公式计算了它的值,使得memo值为数值类型,为什么就不能自定义它的格式了呢,比如说我要定义两位
- delphi报表问题
- 有没有控件数组?
- 如何修改对Windows的区域设置
- 我的Access库文件原来大小是6.78M,我清空所有记录和减少很多记录时,为什么大小没改变?
- 如何搜索本机(web服务器)的默认页面发布站点???急救!!!
- 文件传输:服务器和客户端连接问题。(在线等)
- 怎么在运行期间通过一个字段找出一条纪录,并修改它(不在表上操作),书上讲的不明白……
- 为什么不触发onread事件???
- UDP 数据包问题,可能比较菜
- 关于控件字体居中
线程内部其实是一个循环。以接收数据为例,读线程在它的循环中不断检测读缓冲区有无数据,如无,则继续循环检测;如有,则处理(可以是产生一个数据到达事件)。
这种循环相当于是一个"死"循环(当然,它也是有结束条件的,比如线程被终止则循环结束等),为了在一个循环进行过程中,当前进程还能并行地做其他事,操作系统提供了线程这种编程方式。2. UDP是无连接的SOCKET,所以你无法实现一个线程处理一个VOD终端,或者说是一个线程处理一个VOD终端所对应的UDP SOCKET,因为你的程序并不会(也不能)给每个VOD终端分配一个UDP SOCKET与之连接。
只有TCP SOCKET才能实现一个线程处理一个VOD终端。此时的程序处理过程大致是这样的:
(1) 服务器 : 建立侦听的SOCKET
(2) VOD终端: 请求连接
(3) 服务器 : 接收到连接请求
(4) 服务器 : 创建一个用于连接的SOCKET及其线程
(5) 服务器 : 新创建的SOCKET接受终端的连接请求
(6) 连接建立成功, 可以进行数据通讯了。前面说到的“你的程序并不会(也不能)给每个VOD终端分配一个UDP SOCKET与之连接”,就是因为UDP没有TCP建立连接的过程中的(2)-(6)步骤,因此你只能创建一个用于侦听同时也是用于接收数据的UDP。