流媒体技术之RTSP

流媒体技术之RTSP

标签: RTSP技术移动流媒体
 分类:

     最近对于流媒体技术比较感兴趣,虽然读书的时候学过相关方面的基础知识,但是大学上课,你懂得,一方面理论与实际脱节很严重,另一方面考试完全就是突击。学了和没学一样。好了,吐槽结束,书归正文。

    研究流媒体技术的前提是先明白三个协议,RTSP,RTCP和RTP。关于这三种协议具体的定义百度上可以说是一抓一大把。总的来说, RTSP控制负责控制,包括创建,播放和暂停等操作,RTCP和RTP可以认为是一种协议,最大的区别 是RTCP中没有负载(payload,也就是媒体数据流),RTP则包含了负载。RTCP主要负责传输server和client的状态,如已经接收了多少数据,时间戳是什么,而RTP主要作用就是传输流媒体数据。

    大部分对于RTSP都提到了这一个词:“RTSP是文本协议”,这句话是什么意思?通俗点说,如果你想告诉服务器你的名字,你首先构建一个类似于name="xxxxx"的字符串,然后把这个字符串转成byte[],经过SOCKET传给服务器,服务器就能够知道你的名字了。与之形成对比的是RTCP,RTCP规定了每个比特的每一位都代表什么,例如一个RTCP包的第一个比特的前两位代表版本,第三位用来填充,而第二个比特代表这次会话的序列号。坦率的说,实现RTCP协议可比RTSP烧脑多了。

   回到RTSP这个话题,RTSP协议包含以下几种操作,option,describe,setup,play,pause和teardown。option是询问服务器你能提供什么方法,describe则是获取服务器的详细信息,setup是与服务器建立连接,服务器返回一个sessionid用来之后进行鉴权,play就是通知服务器可以发数据了,pause则是通知服务器暂停发数据,teardown,挥泪告别,さようなら。

   如果你在百度上搜索过如下的关键字:RTSP  Java。你会发现有人已经实现了RTSP协议,如果你真的使用了那份代码,恭喜你,你踩到坑啦。大部分转载的人并没有对转载的内容进行验证。我被网上的这份代码坑了号就,今天刚刚出坑,特此记录。

    RTSPProtocal:RTSP协议类,主要负责创建RTSP文本

    

[java] view plain copy
 
  1. public class RTSPProtocal {  
  2.       
  3.     public static byte[] encodeOption(String address, String VERSION, int seq) {    
  4.         StringBuilder sb = new StringBuilder();    
  5.         sb.append("OPTIONS ");    
  6.         sb.append(address.substring(0, address.lastIndexOf("/")));    
  7.         sb.append(VERSION);    
  8.         sb.append("Cseq: ");    
  9.         sb.append(seq);    
  10.         sb.append("\r\n");    
  11.         sb.append("\r\n");    
  12.         System.out.println(sb.toString());    
  13.         //send(sb.toString().getBytes());  
  14.         return sb.toString().getBytes();  
  15.     }  
  16.       
  17.     public static byte[] encodeDescribe(String address, String VERSION, int seq) {    
  18.         StringBuilder sb = new StringBuilder();    
  19.         sb.append("DESCRIBE ");    
  20.         sb.append(address);    
  21.         sb.append(VERSION);    
  22.         sb.append("Cseq: ");    
  23.         sb.append(seq);    
  24.         sb.append("\r\n");    
  25.         sb.append("\r\n");    
  26.         System.out.println(sb.toString());    
  27.         //send(sb.toString().getBytes());  
  28.         return sb.toString().getBytes();    
  29.     }  
  30.       
  31.     public static byte[] encodeSetup(String address, String VERSION, String sessionid,   
  32.                                         int portOdd, int portEven, int seq, String trackInfo) {    
  33.         StringBuilder sb = new StringBuilder();    
  34.         sb.append("SETUP ");    
  35.         sb.append(address);    
  36.         sb.append("/");    
  37.         sb.append(trackInfo);    
  38.         sb.append(VERSION);    
  39.         sb.append("Cseq: ");    
  40.         sb.append(seq++);    
  41.         sb.append("\r\n");  
  42.         //"50002-50003"  
  43.         sb.append("Transport: RTP/AVP;UNICAST;client_port="+portEven+"-"+portOdd+";mode=play\r\n");    
  44.         sb.append("\r\n");    
  45.         System.out.println(sb.toString());    
  46.         System.out.println(sb.toString());    
  47.         //send(sb.toString().getBytes());    
  48.         return sb.toString().getBytes();  
  49.     }  
  50.       
  51.     public static byte[] encodePlay(String address, String VERSION, String sessionid, int seq) {    
  52.         StringBuilder sb = new StringBuilder();    
  53.         sb.append("PLAY ");    
  54.         sb.append(address);    
  55.         sb.append(VERSION);    
  56.         sb.append("Session: ");    
  57.         sb.append(sessionid);    
  58.         sb.append("Cseq: ");    
  59.         sb.append(seq);  
  60.         sb.append("\r\n");  
  61.         sb.append("Range: npt=0.000-");  
  62.         sb.append("\r\n");    
  63.         sb.append("\r\n");    
  64.         System.out.println(sb.toString());    
  65.         //send(sb.toString().getBytes());    
  66.         return sb.toString().getBytes();  
  67.     }  
  68.       
  69.     public static byte[] encodePause(String address, String VERSION, String sessionid, int seq) {    
  70.         StringBuilder sb = new StringBuilder();    
  71.         sb.append("PAUSE ");    
  72.         sb.append(address);    
  73.         sb.append("/");    
  74.         sb.append(VERSION);    
  75.         sb.append("Cseq: ");    
  76.         sb.append(seq);    
  77.         sb.append("\r\n");    
  78.         sb.append("Session: ");    
  79.         sb.append(sessionid);    
  80.         sb.append("\r\n");    
  81.         System.out.println(sb.toString());    
  82.         //send(sb.toString().getBytes());  
  83.         return sb.toString().getBytes();  
  84.     }  
  85.       
  86.     public static byte[] encodeTeardown(String address, String VERSION, String sessionid, int seq) {    
  87.         StringBuilder sb = new StringBuilder();    
  88.         sb.append("TEARDOWN ");    
  89.         sb.append(address);    
  90.         sb.append("/");    
  91.         sb.append(VERSION);    
  92.         sb.append("Cseq: ");    
  93.         sb.append(seq);    
  94.         sb.append("\r\n");  
  95.         sb.append("User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25)\r\n");    
  96.         sb.append("Session: ");    
  97.         sb.append(sessionid);    
  98.         sb.append("\r\n");  
  99.         System.out.println(sb.toString());   
  100.         return sb.toString().getBytes();  
  101.         //send(sb.toString().getBytes());    
  102.         //   
  103.     }  
  104. }  
   RTSPClient:使用RTSPProtocal中的静态方法获取字符创,拥有发送和接收数据的功能

 

 

[java] view plain copy
 
  1. import java.io.IOException;  
  2. import java.net.InetSocketAddress;  
  3. import java.net.Socket;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.SelectionKey;  
  6. import java.nio.channels.Selector;  
  7. import java.nio.channels.SocketChannel;  
  8. import java.util.HashMap;  
  9. import java.util.Map;  
  10.   
  11. public class RTSPClient {  
  12.       
  13.     private static final int BUFFER_SIZE = 8192;  
  14.       
  15.     private String localIpAddress;  
  16.     private String remoteIpAddress;  
  17.       
  18.     private int localPort;  
  19.     private int localPortOdd;  
  20.     private int localPortEven;  
  21.     private int remoteIPort;  
  22.       
  23.     private int remotePortOdd;  
  24.     private int remotePortEven;  
  25.       
  26.     private Map<Integer, ReceiveSocket> map = new HashMap<>();  
  27.       
  28.       
  29.       
  30.     public int getRemotePortOdd() {  
  31.         return remotePortOdd;  
  32.     }  
  33.     public void setRemotePortOdd(int remotePortOdd) {  
  34.         this.remotePortOdd = remotePortOdd;  
  35.     }  
  36.     public int getRemotePortEven() {  
  37.         return remotePortEven;  
  38.     }  
  39.     public void setRemotePortEven(int remotePortEven) {  
  40.         this.remotePortEven = remotePortEven;  
  41.     }  
  42.       
  43.     public void addSocket(Integer port, ReceiveSocket socket){  
  44.         map.put(port, socket);  
  45.     }  
  46.       
  47.     private String rtspAddress;  
  48.     private Socket tcpSocket;  
  49.       
  50.     private SocketChannel socketChannel;  
  51.     private Selector selector;   
  52.       
  53.     public String getLocalIpAddress() {  
  54.         return localIpAddress;  
  55.     }  
  56.     public void setLocalIpAddress(String localIpAddress) {  
  57.         this.localIpAddress = localIpAddress;  
  58.     }  
  59.     public int getLocalPort() {  
  60.         return localPort;  
  61.     }  
  62.     public void setLocalPort(int localPort) {  
  63.         this.localPort = localPort;  
  64.     }  
  65.     public int getLocalPortOdd() {  
  66.         return localPortOdd;  
  67.     }  
  68.     public void setLocalPortOdd(int localPortOdd) {  
  69.         this.localPortOdd = localPortOdd;  
  70.     }  
  71.     public int getLocalPortEven() {  
  72.         return localPortEven;  
  73.     }  
  74.     public void setLocalPortEven(int localPortEven) {  
  75.         this.localPortEven = localPortEven;  
  76.     }  
  77.     public String getRtspAddress() {  
  78.         return rtspAddress;  
  79.     }  
  80.     public void setRtspAddress(String rtspAddress) {  
  81.         this.rtspAddress = rtspAddress;  
  82.     }  
  83.     public Socket getTcpSocket() {  
  84.         return tcpSocket;  
  85.     }  
  86.     public void setTcpSocket(Socket tcpSocket) {  
  87.         this.tcpSocket = tcpSocket;  
  88.     }  
  89.       
  90.       
  91.     public String getRemoteIpAddress() {  
  92.         return remoteIpAddress;  
  93.     }  
  94.     public void setRemoteIpAddress(String remoteIpAddress) {  
  95.         this.remoteIpAddress = remoteIpAddress;  
  96.     }  
  97.     public int getRemoteIPort() {  
  98.         return remoteIPort;  
  99.     }  
  100.     public void setRemoteIPort(int remoteIPort) {  
  101.         this.remoteIPort = remoteIPort;  
  102.     }  
  103.       
  104.     public Selector getSelector() {  
  105.         return selector;  
  106.     }  
  107.     public void setSelector(Selector selector) {  
  108.         this.selector = selector;  
  109.     }  
  110.     //new InetSocketAddress(    
  111.     //remoteIp, 554),    
  112.     //new InetSocketAddress("192.168.31.106", 0),    
  113.     //"rtsp://218.204.223.237:554/live/1/66251FC11353191F/e7ooqwcfbqjoo80j.sdp"  
  114.     public void inital() throws IOException{  
  115.          socketChannel = SocketChannel.open();     
  116.          socketChannel.socket().setSoTimeout(30000);    
  117.          socketChannel.configureBlocking(false);  
  118.            
  119.          InetSocketAddress localAddress = new InetSocketAddress(this.localIpAddress, localPort);  
  120.          InetSocketAddress remoteAddress=new InetSocketAddress(this.remoteIpAddress, 554);  
  121.            
  122.          socketChannel.socket().bind(localAddress);    
  123.          if (socketChannel.connect(remoteAddress)) {    
  124.              System.out.println("开始建立连接:" + remoteAddress);    
  125.          }   
  126.            
  127.          if (selector == null) {    
  128.              // 创建新的Selector    
  129.              try {    
  130.                  selector = Selector.open();    
  131.              } catch (final IOException e) {    
  132.                  e.printStackTrace();    
  133.              }    
  134.          }  
  135.          socketChannel.register(selector, SelectionKey.OP_CONNECT    
  136.                  | SelectionKey.OP_READ | SelectionKey.OP_WRITE, this);    
  137.          System.out.println("端口打开成功");  
  138.     }  
  139.       
  140.     public void write(byte[] out) throws IOException {    
  141.         if (out == null || out.length < 1) {    
  142.             return;    
  143.         }  
  144.         System.out.println(out.toString());  
  145.         ByteBuffer sendBuf = ByteBuffer.allocateDirect(BUFFER_SIZE);  
  146.         sendBuf.clear();    
  147.         sendBuf.put(out);    
  148.         sendBuf.flip();  
  149.         if (isConnected()) {    
  150.             try {    
  151.                 socketChannel.write(sendBuf);    
  152.             } catch (final IOException e) {    
  153.             }    
  154.         } else {    
  155.             System.out.println("通道为空或者没有连接上");    
  156.         }    
  157.     }  
  158.       
  159.     public boolean isConnected() {    
  160.         return socketChannel != null && socketChannel.isConnected();    
  161.     }  
  162.       
  163.     public byte[] receive() {    
  164.         if (isConnected()) {    
  165.             try {    
  166.                 int len = 0;    
  167.                 int readBytes = 0;  
  168.                 ByteBuffer receiveBuf = ByteBuffer.allocateDirect(BUFFER_SIZE);  
  169.                 synchronized (receiveBuf) {    
  170.                     receiveBuf.clear();    
  171.                     try {    
  172.                         while ((len = socketChannel.read(receiveBuf)) > 0) {    
  173.                             readBytes += len;    
  174.                         }    
  175.                     } finally {    
  176.                         receiveBuf.flip();    
  177.                     }    
  178.                     if (readBytes > 0) {    
  179.                         final byte[] tmp = new byte[readBytes];    
  180.                         receiveBuf.get(tmp);    
  181.                         return tmp;    
  182.                     } else {    
  183.                         System.out.println("接收到数据为空,重新启动连接");    
  184.                         return null;    
  185.                     }    
  186.                 }    
  187.             } catch (final IOException e) {    
  188.                 System.out.println("接收消息错误:");    
  189.             }    
  190.         } else {    
  191.             System.out.println("端口没有连接");    
  192.         }    
  193.         return null;    
  194.     }  
  195.     /* 
  196.      * 非常重要 
  197.      * */  
  198.     public void sendBeforePlay(){  
  199.         ReceiveSocket socketEven = map.get(this.localPortEven);  
  200.         ReceiveSocket socketOdd = map.get(this.localPortOdd);  
  201.         if(socketEven == null){  
  202.             socketEven = new ReceiveSocket(this.localIpAddress,this.localPortEven);  
  203.             map.put(this.localPortEven, socketEven);  
  204.         }  
  205.         if(socketOdd == null){  
  206.             socketEven = new ReceiveSocket(this.localIpAddress, this.localPortOdd);  
  207.             map.put(this.localPortOdd, socketOdd);  
  208.         }  
  209.         byte[] bytes = new byte[1];  
  210.         bytes[0]=0;  
  211.         try {  
  212.             socketEven.send(bytes, this.remoteIpAddress, this.remotePortEven);  
  213.             socketOdd.send(bytes, this.remoteIpAddress, this.remotePortOdd);  
  214.         } catch (IOException e) {  
  215.             e.printStackTrace();  
  216.         }  
  217.         return;  
  218.     }  
  219.       
  220.     public void reConnect(SelectionKey key) throws IOException {    
  221.         if (isConnected()) {    
  222.             return;    
  223.         }    
  224.         // 完成SocketChannel的连接    
  225.         socketChannel.finishConnect();    
  226.         while (!socketChannel.isConnected()) {    
  227.             try {    
  228.                 Thread.sleep(300);    
  229.             } catch (final InterruptedException e) {    
  230.                 e.printStackTrace();    
  231.             }    
  232.             socketChannel.finishConnect();    
  233.         }    
  234.     
  235.     }  
  236. }  
   ReceiveSocket:用来接收服务器发来的RTP和RTCP协议数据,只是简单地对UDP进行了包装而已

 

 

[java] view plain copy
 
  1. import java.io.IOException;  
  2. import java.net.DatagramPacket;  
  3. import java.net.DatagramSocket;  
  4. import java.net.InetAddress;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.SocketException;  
  7. import java.net.UnknownHostException;  
  8.   
  9.   
  10. public class ReceiveSocket implements Runnable{  
  11.       
  12.     private DatagramSocket ds;  
  13.     public ReceiveSocket(String localAddress, int port){  
  14.          try {  
  15.               
  16.             InetSocketAddress addr = new InetSocketAddress("192.168.31.106", port);  
  17.             ds = new DatagramSocket(addr);//监听16264端口  
  18.         } catch (SocketException e) {  
  19.             e.printStackTrace();  
  20.         }     
  21.     }  
  22.       
  23.     @Override  
  24.     public void run() {  
  25.         // TODO Auto-generated method stub  
  26.         while(true){  
  27.             byte[] buf = new byte[20];    
  28.             DatagramPacket dp = new DatagramPacket(buf,buf.length);    
  29.             try   
  30.             {  
  31.                 ds.receive(dp);  
  32.                 String ip = dp.getAddress().getHostAddress();   //数据提取    
  33.                 String data = new String(dp.getData(),0,dp.getLength());    
  34.                 int port = dp.getPort();    
  35.                 System.out.println(data+"."+port+".."+ip);  
  36.             } catch (IOException e) {  
  37.                 // TODO Auto-generated catch block  
  38.                 e.printStackTrace();  
  39.             }     
  40.         }      
  41.     }  
  42.       
  43.     public void send(byte[] buf, String ip, int rec_port) throws IOException {  
  44.         // TODO Auto-generated method stub  
  45.         DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName(ip),rec_port);//10000为定义的端口       
  46.         ds.send(dp);    
  47.         //ds.close();      
  48.     }  
  49. }  
    PlayerClient:播放类,通过不同状态之间的相互转化完成RTSP协议的交互工作。这里有一点非常关键:请注意setup这个状态,在和服务器建立连接之后,如果直接发送PLAY请求,服务器不会向指定的端口发送RTCP数据(这个问题困扰了我一晚上)。因此在发送PLAY请求之前,client接收RTCP和RTP的两个端口必须先向服务器的RTCP和RTP端口发送任意的数据,发送方式为UDP,服务器在setup操作时已经返回RTCP和RTP的端口信息。具体的实现参考sendBeforePlay()。我在网上没有找到这么操作的原因,这还是通过wireshark对VLC进行抓包才发现这个隐藏逻辑。
[java] view plain copy
 
  1. import java.io.IOException;  
  2. import java.nio.channels.SelectionKey;  
  3. import java.nio.channels.Selector;  
  4. import java.util.Iterator;  
  5.   
  6.   
  7. public class PlayerClient {  
  8.     private RTSPClient rtspClient = new RTSPClient();  
  9.     private static final String VERSION = " RTSP/1.0\r\n";    
  10.     private static final String RTSP_OK = "RTSP/1.0 200 OK";  
  11.     private Selector selector;  
  12.     private enum Status {    
  13.         init, options, describe, setup, play, pause, teardown    
  14.     }  
  15.     private Status sysStatus = Status.init;  
  16.     private String rtspAddress = "rtsp://218.204.223.237:554/live/1/66251FC11353191F/e7ooqwcfbqjoo80j.sdp";  
  17.     private String localAddress = "192.168.31.106";  
  18.     private int localPort=0;  
  19.     private String remoteAddress = "218.204.223.237";  
  20.     private int count=0;  
  21.     private String sessionid;  
  22.     private String trackInfo;  
  23.     private boolean isSended=true;  
  24.     private int localPortOdd=50002;  
  25.     private int localPortEven=50003;  
  26.     private ReceiveSocket socket1 = new ReceiveSocket(localAddress,localPortOdd);  
  27.     private ReceiveSocket socket2 = new ReceiveSocket(localAddress,localPortEven);  
  28.       
  29.     public void init(){  
  30.         rtspClient.setLocalIpAddress(localAddress);  
  31.         rtspClient.setLocalPort(localPort);  
  32.         rtspClient.setRemoteIpAddress(remoteAddress);  
  33.         rtspClient.setRemoteIPort(554);  
  34.         rtspClient.setRtspAddress(rtspAddress);  
  35.         rtspClient.setLocalPortEven(this.localPortEven);  
  36.         rtspClient.setLocalPortOdd(this.localPortOdd);  
  37.         rtspClient.addSocket(this.localPortOdd, socket1);  
  38.         rtspClient.addSocket(this.localPortEven, socket2);  
  39.         try   
  40.         {  
  41.             rtspClient.inital();  
  42.         } catch (IOException e) {  
  43.             e.printStackTrace();  
  44.         }  
  45.         this.selector = rtspClient.getSelector();  
  46.         new Thread(socket1).start();  
  47.         new Thread(socket2).start();  
  48.     }  
  49.       
  50.     public void run() throws IOException{  
  51.         int seq=2;  
  52.         while(true){  
  53.             if(rtspClient.isConnected() && isSended){  
  54.                 switch (sysStatus) {    
  55.                 case init:  
  56.                     byte[] message = RTSPProtocal.encodeOption(this.rtspAddress, this.VERSION, seq);  
  57.                     this.rtspClient.write(message);   
  58.                     break;    
  59.                 case options:  
  60.                     seq++;  
  61.                     message = RTSPProtocal.encodeDescribe(this.rtspAddress, this.VERSION, seq);  
  62.                     this.rtspClient.write(message);     
  63.                     break;    
  64.                 case describe:    
  65.                     seq++;  
  66.                     message = RTSPProtocal.encodeSetup(this.rtspAddress, VERSION, sessionid,   
  67.                                                 localPortEven, localPortOdd,seq, trackInfo);  
  68.                     this.rtspClient.write(message);    
  69.                     break;    
  70.                 case setup:    
  71.                     if(sessionid==null&&sessionid.length()>0){    
  72.                         System.out.println("setup还没有正常返回");    
  73.                     }else{    
  74.                         seq++;  
  75.                         message = RTSPProtocal.encodePlay(this.rtspAddress, VERSION, sessionid, seq);  
  76.                         this.rtspClient.write(message);   
  77.                     }    
  78.                     break;    
  79.                 case play:  
  80.                     count++;  
  81.                     System.out.println("count: "+count);  
  82.                     break;  
  83.                 case pause:     
  84.                     break;    
  85.                 default:    
  86.                     break;    
  87.                 }  
  88.                 isSended=false;  
  89.             }  
  90.             else{  
  91.                   
  92.             }  
  93.             select();  
  94.         }  
  95.     }  
  96.       
  97.     private void handle(byte[] msg) {    
  98.         String tmp = new String(msg);    
  99.         System.out.println("返回内容:"+tmp);    
  100.         if (tmp.startsWith(RTSP_OK)) {    
  101.             switch (sysStatus) {    
  102.             case init:    
  103.                 sysStatus = Status.options;    
  104.                 System.out.println("option ok");  
  105.                 isSended=true;   
  106.                 break;    
  107.             case options:    
  108.                 sysStatus = Status.describe;    
  109.                 trackInfo=tmp.substring(tmp.indexOf("trackID"));    
  110.                 System.out.println("describe ok");   
  111.                 isSended=true;   
  112.                 break;    
  113.             case describe:    
  114.                 sessionid = tmp.substring(tmp.indexOf("Session: ") + 9, tmp    
  115.                         .indexOf("Date:"));    
  116.                 int index = tmp.indexOf("server_port=");  
  117.                 String serverPort1 = tmp.substring(tmp.indexOf("server_port=") + 12, tmp    
  118.                         .indexOf("-", index));  
  119.                 String serverPort2 = tmp.substring(tmp.indexOf("-", index) + 1, tmp    
  120.                         .indexOf("\r\n", index));  
  121.                   
  122.                 this.rtspClient.setRemotePortEven(Integer.valueOf(serverPort1));  
  123.                 this.rtspClient.setRemotePortOdd(Integer.valueOf(serverPort2));  
  124.                   
  125.                 if(sessionid!=null&&sessionid.length()>0){    
  126.                     sysStatus = Status.setup;    
  127.                     System.out.println("setup ok");    
  128.                 }  
  129.                 isSended=true;   
  130.                 break;    
  131.             case setup:    
  132.                 sysStatus = Status.play;     
  133.                 System.out.println("play ok");   
  134.                 this.rtspClient.sendBeforePlay();  
  135.                 this.rtspClient.sendBeforePlay();  
  136.                 isSended=true;   
  137.                 break;    
  138.             case play:    
  139.                 //sysStatus = Status.pause;    
  140.                 System.out.println("pause ok");    
  141.                 isSended=true;   
  142.                 break;    
  143.             case pause:    
  144.                 sysStatus = Status.teardown;    
  145.                 System.out.println("teardown ok");   
  146.                 isSended=true;   
  147.                 //shutdown.set(true);    
  148.                 break;    
  149.             case teardown:    
  150.                 sysStatus = Status.init;    
  151.                 System.out.println("exit start");   
  152.                 isSended=true;   
  153.                 break;    
  154.             default:    
  155.                 break;    
  156.             }     
  157.         } else {    
  158.             System.out.println("返回错误:" + tmp);    
  159.         }    
  160.     
  161.     }  
  162.       
  163.     private void select() {    
  164.         int n = 0;    
  165.         try   
  166.         {    
  167.             if (selector == null) {    
  168.                 return;    
  169.             }    
  170.             n = selector.select(1000);    
  171.         } catch (final Exception e) {    
  172.             e.printStackTrace();    
  173.         }    
  174.     
  175.         // 如果select返回大于0,处理事件    
  176.         if (n > 0) {    
  177.             for (final Iterator<SelectionKey> i = selector.selectedKeys()    
  178.                     .iterator(); i.hasNext();) {    
  179.                 // 得到下一个Key    
  180.                 final SelectionKey sk = i.next();    
  181.                 i.remove();    
  182.                 // 检查其是否还有效    
  183.                 if (!sk.isValid()) {    
  184.                     continue;    
  185.                 }    
  186.                 if (sk.isReadable()) {    
  187.                     byte[] message = rtspClient.receive();  
  188.                     handle(message);  
  189.                 }  
  190.                 if (sk.isConnectable()) {    
  191.                     try {  
  192.                         rtspClient.reConnect(sk);  
  193.                     } catch (IOException e) {  
  194.                         // TODO Auto-generated catch block  
  195.                         e.printStackTrace();  
  196.                     }    
  197.                 }  
  198.             }    
  199.         }    
  200.     }  
  201.       
  202. }  
Test:测试类

 

 

[java] view plain copy
 
  1. public class Test {  
  2.     public static void main(String[] args){  
  3.         PlayerClient player = new PlayerClient();  
  4.         player.init();  
  5.         try   
  6.         {  
  7.             player.run();  
  8.         } catch (IOException e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.     }  
  12. }  
   只要在ReceiveSocket的run方法中打断点,你就会发现源源不断的数据向你发来,是不是感觉很爽,哈哈哈。
posted @ 2016-09-29 10:41  吃饭了吗  阅读(467)  评论(0编辑  收藏  举报