• 流媒体技术之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(" ");    
    11.         sb.append(" ");    
    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(" ");    
    25.         sb.append(" ");    
    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(" ");  
    42.         //"50002-50003"  
    43.         sb.append("Transport: RTP/AVP;UNICAST;client_port="+portEven+"-"+portOdd+";mode=play ");    
    44.         sb.append(" ");    
    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(" ");  
    61.         sb.append("Range: npt=0.000-");  
    62.         sb.append(" ");    
    63.         sb.append(" ");    
    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(" ");    
    78.         sb.append("Session: ");    
    79.         sb.append(sessionid);    
    80.         sb.append(" ");    
    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(" ");  
    95.         sb.append("User-Agent: LibVLC/2.2.1 (LIVE555 Streaming Media v2014.07.25) ");    
    96.         sb.append("Session: ");    
    97.         sb.append(sessionid);    
    98.         sb.append(" ");  
    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 ";    
    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(" ", 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方法中打断点,你就会发现源源不断的数据向你发来,是不是感觉很爽,哈哈哈。
  • 相关阅读:
    中国历史朝代公元对照简表
    [Solved] DashBoard – Excel Service: The data sources may be unreachable, may not be responding, or may have denied you access.
    Delete/Remove Project from TFS 2010
    Sharepoint site showing system account instead of my username on the top right corner.
    你的成功在于你每天养成的习惯
    Internet Information Services is running in 32bit emulation mode. Correct the issue listed above and rerun setup.
    Prepare to back up and restore a farm (Office SharePoint Server 2007)
    Word中字号与磅值的对应关系
    How to: Change the Frequency for Refreshing the Data Warehouse for Team System
    UI Automation in WPF/Silverlight
  • 原文地址:https://www.cnblogs.com/developer-ios/p/5919024.html
Copyright © 2020-2023  润新知