小弟在公司维护一套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;

解决方案 »

  1.   

    直接用indy的控件,应该很简单的就可解决你的需求
      

  2.   

    1. 事件是由线程产生了。
        线程内部其实是一个循环。以接收数据为例,读线程在它的循环中不断检测读缓冲区有无数据,如无,则继续循环检测;如有,则处理(可以是产生一个数据到达事件)。
        这种循环相当于是一个"死"循环(当然,它也是有结束条件的,比如线程被终止则循环结束等),为了在一个循环进行过程中,当前进程还能并行地做其他事,操作系统提供了线程这种编程方式。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。