• Java Socket长连接示例代码


    SocketListenerPusher.java代码如下: 

    Java代码  收藏代码
    1. import java.io.IOException;  
    2. import java.net.InetSocketAddress;  
    3. import java.net.ServerSocket;  
    4. import java.net.Socket;  
    5. import java.util.concurrent.ExecutorService;  
    6. import java.util.concurrent.Executors;  
    7. import java.util.concurrent.ScheduledThreadPoolExecutor;  
    8. import java.util.concurrent.TimeUnit;  
    9.   
    10. import org.apache.commons.configuration.ConfigurationException;  
    11. import org.directwebremoting.impl.DaemonThreadFactory;  
    12. import org.slf4j.Logger;  
    13. import org.slf4j.LoggerFactory;  
    14.   
    15. import com.shihuan.dragonkeeper.common.utils.PropertiesUtil;  
    16. import com.shihuan.dragonkeeper.global.ConfigFile;  
    17.   
    18. public class SocketListenerPusher implements Runnable {  
    19.   
    20.     protected static Logger logger = LoggerFactory.getLogger(SocketListenerPusher.class);  
    21.       
    22.     public static String socketlistenerserver_CONFIG = ConfigFile.SOCKETLISTENERSERVER__CONFIG + ConfigFile.SUFFIX_NAME;  
    23.       
    24.     private ServerSocket serverSocket;  
    25.     private ExecutorService pool;  
    26.       
    27.       
    28.     public SocketListenerPusher() {  
    29.         int port = 0;  
    30.         int poolsize = 0;  
    31.           
    32.         try {  
    33.             port = Integer.parseInt(PropertiesUtil.getPropertiesValue(socketlistenerserver_CONFIG, "serverport"));  
    34.             poolsize = Integer.parseInt(PropertiesUtil.getPropertiesValue(socketlistenerserver_CONFIG, "poolsize"));  
    35.               
    36.             serverSocket = new ServerSocket();  
    37.             serverSocket.setReuseAddress(true);  
    38.             serverSocket.bind(new InetSocketAddress(port));  
    39.             pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * poolsize);  
    40.               
    41.             //下面两句循环执行run()方法, 相当于while(true){...}  
    42.             ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new DaemonThreadFactory());  
    43.             executor.scheduleAtFixedRate(this, 1L, 1L, TimeUnit.MILLISECONDS);  
    44.               
    45.         } catch (NumberFormatException e) {  
    46.             logger.error(e.getMessage(), e);  
    47.             e.printStackTrace();  
    48.         } catch (ConfigurationException e) {  
    49.             logger.error(e.getMessage(), e);  
    50.             e.printStackTrace();  
    51.         } catch (IOException e) {  
    52.             logger.error(e.getMessage(), e);  
    53.             e.printStackTrace();  
    54.         }  
    55.   
    56.     }  
    57.       
    58.     public void run() {  
    59.         Socket socket = null;  
    60.         try {  
    61.             socket = serverSocket.accept();  
    62.             pool.execute(new SocketListenerHandler(socket));  
    63.         } catch (IOException e) {  
    64.             System.out.println("线程池被关闭!!!!!!!!!!!");  
    65.             pool.shutdown();  
    66.             logger.error(e.getMessage(), e);  
    67.             e.printStackTrace();  
    68.         }  
    69.           
    70.     }  


    SocketListenerHandler.java代码如下: 

    Java代码  收藏代码
    1. import java.io.BufferedInputStream;  
    2. import java.io.BufferedReader;  
    3. import java.io.IOException;  
    4. import java.io.InputStreamReader;  
    5. import java.io.ObjectInputStream;  
    6. import java.net.Socket;  
    7. import java.sql.Connection;  
    8. import java.sql.SQLException;  
    9.   
    10. import org.apache.commons.configuration.ConfigurationException;  
    11. import org.apache.commons.dbutils.DbUtils;  
    12. import org.apache.commons.dbutils.QueryRunner;  
    13. import org.apache.commons.io.IOUtils;  
    14. import org.directwebremoting.Browser;  
    15. import org.directwebremoting.ScriptSessions;  
    16. import org.slf4j.Logger;  
    17. import org.slf4j.LoggerFactory;  
    18.   
    19. import com.alibaba.fastjson.JSON;  
    20. import com.shihuan.dragonkeeper.common.dto.DataSourceInfo;  
    21. import com.shihuan.dragonkeeper.common.utils.ByteArrayUtil;  
    22. import com.shihuan.dragonkeeper.common.utils.DataSourceMapUtil;  
    23. import com.shihuan.dragonkeeper.common.utils.DateFormatterUtil;  
    24. import com.shihuan.dragonkeeper.common.utils.PropertiesUtil;  
    25. import com.shihuan.dragonkeeper.global.ConfigFile;  
    26. import com.shihuan.dragonkeeper.server.bean.ActivityServiceBean;  
    27.   
    28. public class SocketListenerHandler implements Runnable {  
    29.   
    30.     protected static Logger logger = LoggerFactory.getLogger(SocketListenerHandler.class);  
    31.       
    32.     private static String jdbc_CONFIG = ConfigFile.JDBC_CONFIG + ConfigFile.SUFFIX_NAME;  
    33.       
    34.     public static final int timeOut = 0*1000 ;  //设置读取操作异常为1秒  
    35.     private final String dataRealTimeAction_id = "Agentdata_" + Math.random();  
    36.       
    37.     private static final String noData = "{'nodata':'心跳信息'}";  
    38.     private static final String errorData = "{'error':'无法解析的请求'}";  
    39.       
    40.       
    41.     private Socket connectedsocket = null;  
    42.       
    43.     public SocketListenerHandler(Socket socket){  
    44.         this.connectedsocket = socket;  
    45.     }  
    46.   
    47. @Override  
    48.     public void run() {  
    49.         BufferedReader in = null;  
    50. String resultData = "";  
    51.           
    52.         try {  
    53.             connectedsocket.setSoTimeout(timeOut);  //表示接收数据时的等待超时数据, 此方法必须在接收数据之前执行才有效. 此外, 当输入流的 read()方法抛出 SocketTimeoutException后, Socket仍然是连接的, 可以尝试再次读数据, 单位为毫秒, 它的默认值为 0(表示会无限等待, 永远不会超时)  
    54.             connectedsocket.setKeepAlive(false);   //表示对于长时间处于空闲状态的Socket, 是否要自动把它关闭.  
    55.               
    56.             in = new BufferedReader(new InputStreamReader(connectedsocket.getInputStream()));  
    57. if (in.ready()) {  //判断流中是否有数据  
    58.                   
    59.                 resultData = getNoHeadData(in.readLine());   //从Agent端接收到的数据  
    60.                 logger.info("#### 结果DATA = "+resultData);  
    61.                   
    62.                 if (resultData==null || "".equals(resultData)) {  
    63.                     logger.info(dataRealTimeAction_id + " -->>> " + "内容为空!");  
    64.                 } else if (resultData.charAt(0) != '{') {  //要在客户端定时维持心跳信息  
    65.                     logger.info(dataRealTimeAction_id + " -->>> " + noData);  
    66.                 } else {  
    67.                     ActivityServiceBean asb = JSON.parseObject(resultData, ActivityServiceBean.class);  
    68.                     System.out.println("打印预处理信息Start......");  
    69.                     System.out.println(asb.getProxyname() + " -- " + asb.getIp() + " -- " + asb.getCalltime() + " -- " + asb.getAnswertime() + " -- " + asb.getCpu() + " -- " + asb.getThread() + " -- " + asb.getStatus() + " -- " + asb.getAccessaddress() + " -- " + asb.getAccessfilename() + " -- " + asb.getSql() + " -- " + asb.getContent());  
    70.                     System.out.println("打印预处理信息End......");  
    71. //                  parseData(ois);  
    72.                       
    73.                     logger.info(dataRealTimeAction_id + ": 成功处理了接收到的数据!");  
    74.                 }  
    75.                   
    76.             }  
    77. catch (IOException e) {  
    78.             logger.error(e.getMessage() + " " + errorData, e);  
    79.             e.printStackTrace();  
    80.         } catch (NumberFormatException e) {  
    81.             logger.error(e.getMessage(), e);  
    82.             e.printStackTrace();  
    83.         } finally {  
    84.               
    85.             if (in != null) {  
    86.                 try {  
    87.                     in.close();  
    88.                 } catch (IOException e) {  
    89.                     logger.error(e.getMessage(), e);  
    90.                     e.printStackTrace();  
    91.                 }  
    92.             }  
    93. }  
    94.           
    95.     }  



    TestSocketListenerPusher.java请求端代码如下: 

    Java代码  收藏代码
    1. import java.io.BufferedOutputStream;  
    2. import java.io.IOException;  
    3. import java.io.OutputStream;  
    4. import java.net.Socket;  
    5. import java.net.UnknownHostException;  
    6. import java.util.Date;  
    7.   
    8. import org.apache.commons.configuration.ConfigurationException;  
    9.   
    10. import com.alibaba.fastjson.JSON;  
    11. import com.shihuan.dragonkeeper.common.utils.ByteArrayUtil;  
    12. import com.shihuan.dragonkeeper.common.utils.PropertiesUtil;  
    13. import com.shihuan.dragonkeeper.global.ConfigFile;  
    14. import com.shihuan.dragonkeeper.server.bean.ActivityServiceBean;  
    15.   
    16. public class TestSocketListenerPusher implements Runnable {  
    17.   
    18.     private static String socketlistenerserver_CONFIG = ConfigFile.SOCKETLISTENERSERVER__CONFIG + ConfigFile.SUFFIX_NAME;  
    19.       
    20.     private Socket socketclient = null;  
    21.       
    22.     @Override  
    23.     public void run() {  
    24.           
    25.         String serverip = "";  
    26.         int port = 0;  
    27.           
    28.         OutputStream os = null;  
    29.           
    30.         try {  
    31.             serverip = PropertiesUtil.getPropertiesValue(socketlistenerserver_CONFIG, "serverip");  
    32.             port = Integer.parseInt(PropertiesUtil.getPropertiesValue(socketlistenerserver_CONFIG, "serverport"));  
    33.               
    34.               
    35.             ActivityServiceBean asb = null;  
    36.               
    37.             for (int i=0; i<2; i++) {  
    38.                 asb = new ActivityServiceBean();  
    39.                 asb.setProxyname("testProxyname"+i);  
    40.                 asb.setIp("testIp"+i);  
    41.                 Date curdate = new Date();  
    42.                 asb.setCalltime(curdate);  
    43.                 asb.setAnswertime(curdate);  
    44.                 asb.setCpu("testCpu"+i);  
    45.                 asb.setThread("testThread"+i);  
    46.                 asb.setStatus("testStatus"+i);  
    47.                 asb.setAccessaddress("testAccessaddress"+i);  
    48.                 asb.setAccessfilename("testAccessfilename"+i);  
    49.                 asb.setSql("testSql"+i);  
    50.                 asb.setContent("testContent"+i);  
    51.                   
    52.                 String jsonStr = JSON.toJSONString(asb).trim();  
    53.                 byte[] information = (new String(ByteArrayUtil.getIntToByte(jsonStr.length()))+jsonStr).getBytes();  
    54.                   
    55.                 System.out.println(information.length);  
    56.                   
    57.                 socketclient = new Socket(serverip, port);  
    58.                 socketclient.setSoTimeout(0);  
    59.                 socketclient.setKeepAlive(false);  
    60.                   
    61.                 os = new BufferedOutputStream(socketclient.getOutputStream());  
    62.                 os.write(information);  
    63.                 os.flush();  
    64.                   
    65.                 System.out.println("Client" + i + " -->>> " + new String(ByteArrayUtil.getIntToByte(jsonStr.length()))+jsonStr);  
    66.                   
    67.                 os.close();  
    68.                 Thread.sleep(3000);  
    69.             }  
    70.               
    71.               
    72.         } catch (ConfigurationException e) {  
    73.             e.printStackTrace();  
    74.         } catch (UnknownHostException e) {  
    75.             e.printStackTrace();  
    76.         } catch (IOException e) {  
    77.             e.printStackTrace();  
    78.         } catch (InterruptedException e) {  
    79.             e.printStackTrace();  
    80.         } finally {  
    81.             /* 
    82.             try { 
    83.                 if (os != null) { 
    84.                     os.close(); 
    85.                 } 
    86.             } catch (IOException e) { 
    87.                 e.printStackTrace(); 
    88.             } 
    89.             */  
    90.         }  
    91.           
    92.           
    93.     }  
    94.       
    95.     public static void main(String[] args) {  
    96.         Thread t = new Thread(new TestSocketListenerPusher());  
    97.         t.start();  
    98.     }  
    99.   
    100. }  




    源代码在笔者shihuan8@163.com邮箱网盘中J2EE代码文件夹里。 

    ---------------------------------------------------------------------------------- 
    如果是按byte[]传输数据的情况,请参考如下代码: 

    SimpleSocketServer.java代码如下: 

    Java代码  收藏代码
    1. package com.shihuan.socket;  
    2.   
    3. import java.io.BufferedInputStream;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.net.InetSocketAddress;  
    7. import java.net.ServerSocket;  
    8. import java.net.Socket;  
    9.   
    10. public class SimpleSocketServer {  
    11.   
    12.     public static void main(String[] args) {  
    13.         try {  
    14.             ServerSocket ss = new ServerSocket();  
    15.             ss.setReuseAddress(true);  //两个进程共用同一个端口的时候,一个进程关闭后,另一个进程还能够立刻重用相同端口  
    16.             ss.setReceiveBufferSize(128*1024);  //缓冲区中允许接收的最大字节数,默认是8192  
    17.             ss.bind(new InetSocketAddress(19990));   
    18.               
    19.             Socket client = ss.accept();  
    20.             InputStream in = new BufferedInputStream(client.getInputStream());  
    21.               
    22.             byte tmpb = (byte)in.read();  
    23.             System.out.println("第一个字节的byte值 --->> " + tmpb);  
    24.             System.out.println("接收字节 --->> " + in.available());  
    25.             byte[] bc = new byte[in.available()+1];  
    26.             bc[0] = tmpb;  
    27.             in.read(bc, 1, in.available());  
    28.               
    29.             System.out.println(bc.length);  
    30.             System.out.println(new String(bc));  
    31.             in.close();  
    32.         } catch (IOException e) {  
    33.             System.out.println(e.getMessage());  
    34.             e.printStackTrace();  
    35.         }  
    36.   
    37.     }  
    38.   
    39. }  



    SimpleSocketClient.java代码如下: 

    Java代码  收藏代码
    1. package com.shihuan.socket;  
    2.   
    3. import java.io.BufferedOutputStream;  
    4. import java.io.IOException;  
    5. import java.io.OutputStream;  
    6. import java.net.Socket;  
    7. import java.net.UnknownHostException;  
    8.   
    9. public class SimpleSocketClient {  
    10.   
    11.     public static void main(String[] args) throws UnknownHostException {  
    12.         try {  
    13.             Socket s = new Socket("192.168.1.10", 19990);  
    14.             OutputStream os = new BufferedOutputStream(s.getOutputStream());  
    15.             String info = "abc!";  
    16.             info = "大家好!";  
    17.             byte[] bi = info.getBytes();  
    18.             os.write(bi);  
    19.             os.flush();  
    20.             os.close();  
    21.         } catch (IOException e) {  
    22.             System.out.println(e.getMessage());  
    23.             e.printStackTrace();  
    24.         }  
    25.     }  
    26.   
    27. }  



    稍微复杂一点儿代码示例,处理了粘包问题: 
    StartListenerTcpThread.java代码: 

    Java代码  收藏代码
    1. import java.io.BufferedInputStream;  
    2. import java.io.IOException;  
    3. import java.io.InputStream;  
    4. import java.net.InetSocketAddress;  
    5. import java.net.ServerSocket;  
    6. import java.net.Socket;  
    7. import java.net.SocketAddress;  
    8. import java.util.Vector;  
    9. import java.util.concurrent.ExcutorService;  
    10. import java.util.concurrent.Excutors;  
    11.   
    12. import org.apache.commons.io.IUtils;  
    13. import org.slf4j.Logger;  
    14. import org.slf4j.LoggerFactory;  
    15.   
    16. import com.shihuan.dragonkeeper.common.utils.ByteArrayUtil;  
    17. import com.shihuan.dragonkeeper.global.ConfigFile;  
    18.   
    19. public class StartListenerTcpThread implements Runnable {  
    20.    public static Logger logger = LoggerFactory.getLogger(StartListenerTcpThread.class);  
    21.   
    22.    private static ExcutorService Threadpool = Excutors.newCachedThreadPool();  
    23.    private static boolean businessflag = true;  
    24.    private static final int receiveBufferSize = 128;  
    25.    private static Vector<byte[]> tmpbytes = new Vector<byte[]>();  
    26.    private ServerSocket serverSocket = null;  
    27.   
    28.    public StartListenerTcpThread(String ip, int port){  
    29.       try{  
    30.          serverSocket = new ServerSocket();  
    31.          serverSocket.setReuseAddress(true);  
    32.          serverSocket.setReceiveBufferSize(receiveBufferSize*1024);  
    33.          serverSocket.setSoTimeout(0);  
    34.          SocketAddress sa = new InetSocketAddress(port);  
    35.          serverSocket.bind(sa, 20);  
    36.       }catch(IOException e){  
    37.          logger.error(e.getMessage(), e);  
    38.       }  
    39.    }  
    40.   
    41.    public void run(){  
    42.       Socket socket = null;  
    43.       while(true){  
    44.          if(businessflag){  
    45.             try{  
    46.                socket = serverSocket.accept();  
    47.                System.out.println("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());  
    48.                InputStream socketIn = new BufferedInputStream(socket.getInputStream());  
    49.                byte tmpb = (byte)socketIn.read();  
    50.                byte[] currentbytes = null;  
    51.                if(tmpbytes.size() > 0){  //上一次IO流中有未处理的剩余包  
    52.                   int oldBytesLen = tmpbytes.get(0).length;  
    53.                   int socketBytesLen = socketIn.available()+1;  
    54.                   int currentLength = oldByteLen + socketBytesLen;  
    55.                   currentbytes = new byte[currentLength];  
    56.                   System.arraycopy(tmpbytes.get(0), 0, currentbytes, oldBytesLen);  
    57.                   currentbytes[oldBytesLen] = tmpb;  
    58.                   socketIn.read(currentbytes, oldBytesLen+1, socketBytesLen-1);  
    59.                   socketIn.close();  
    60.                   splitInputStreamByte(currentbytes);  
    61.                }else{  //正常未粘包情况  
    62.                   int socketBytesLen = socketIn.available()+1;  
    63.                   currentbytes = new byte[socketBytesLen];  
    64.                   currentbytes[0] = tmpb;  
    65.                   socketIn.read(currentbytes, 1, socketBytesLen-1);  
    66.                   socketIn.close();  
    67.                   splitInputStreamByte(currentbytes);  
    68.                }  
    69.             }catch(IOException e){  
    70.                logger.error(e.getMessage(), e);  
    71.             }  
    72.          }  
    73.       }  
    74.    }  
    75.   
    76.    /** 
    77.     * 拆分byte数组并分多线程处理 
    78.     * @param parambytes 原byte数组 
    79.     * @return 处理后剩余部分的byte数组 
    80.    */  
    81.    private static void splitInputStreamByte(byte[] parambytes) {  
    82.       if(parambytes != null){  
    83.          if(parambytes.length > 4){  
    84.             byte[] head = new byte[4];  //单包长度  
    85.             System.arraycopy(parambytes, 0, head, 0, 4);  
    86.             int bodyLength = ByteArrayUtil.getint(head);  
    87.             if(bodyLength <= parambytes.length-4){  
    88.                final byte[] body = new byte[bodyLength];  
    89.                System.arraycopy(parambytes, 4, body, 0, bodyLength);  
    90.                ThreadPool.execute(new Runnable(){  
    91.                   public void run(){  
    92.                      byte[] processDatas = body;  
    93.                      try{  
    94.                         System.out.println(IOUtils.toString(processDatas, "UTF-8").trim());  
    95.                      }catch(IOException e){  
    96.                         logger.error(e.getMessage(), e);  
    97.                      }  
    98.                   }  
    99.                });  
    100.   
    101.                int resultLen = parambytes.length-4-bodyLength;  
    102.                if(resultLen == 0){  
    103.                   splitInputStreamByte(null);  
    104.                }else{  
    105.                   byte[] resultbytes = new byte[resultLen];  
    106.                   System.arraycopy(parambytes, 4+bodyLength, resultbytes, 0, resultLen);  
    107.                   splitInputStreamByte(resultbytes);  
    108.                }  
    109.             }else{  
    110.                tmpbytes.clear();  
    111.                tmpbytes.add(parambytes);  
    112.             }  
    113.          }else{  
    114.             tmpbytes.clear();  
    115.             tmpbytes.add(parambytes);  
    116.          }  
    117.       }  
    118.    }  
    119.   
    120.    public static void openflag(){  
    121.       businessflag = true;  
    122.    }  
    123.   
    124.    public static void closeflag(){  
    125.       businessflag = false;  
    126.    }  
    127.   
    128. }  



    TestTcpSocket.java代码: 

    Java代码  收藏代码
    1. import java.io.IOException;  
    2. import java.io.OutputStream;  
    3. import java.net.Socket;  
    4. import java.net.UnknownHostException;  
    5.   
    6. import com.shihuan.dragonkeeper.common.utils.ByteArrayUtil;  
    7. import com.shihuan.dragonkeeper.global.ConfigFile;  
    8.   
    9. public class TestTcpSocket implements Runnable{  
    10.    private Socket socketClient = null;  
    11.   
    12.    public void run(){  
    13.       String serverip = "192.168.1.10";  
    14.       int port = 19990;  
    15.       try{  
    16.          while(true){  
    17.            System.out.println("SocketClient start......");  
    18.            String mystr = "hello everyone!";  
    19.            socketClient = new Socket(serverip, port);  
    20.            OutputStream os = socketClient.getOutputStream();  
    21.            byte[] head = ByteArrayUtil.int2byte(mystr.length());  
    22.            byte[] body = mystr.getBytes();  
    23.            byte[] total = ByteArrayUtil.byteMerge(head, body);  
    24.   
    25.            os.write(total);  
    26.            os.flush();  
    27.            os.close();  
    28.   
    29.            Thread.sleep(1000);  
    30.   
    31.            System.out.println("SocketClient end......");  
    32.          }  
    33.       }catch(Exception e){  
    34.          logger.error(e.getMessage(), e);  
    35.       }  
    36.    }  
    37.   
    38.    public static void main(String[] args){  
    39.       Thread t = new Thread(new TestTcpSocket());  
    40.       t.start();  
    41.    }  
    42. }   



    下面写ByteArrayUtil.java代码: 

    Java代码  收藏代码
    1. package com.shihuan.dragonkeeper.common.utils;  
    2.   
    3. public class ByteArrayUtil {  
    4.   
    5.    /** 
    6.     * 将int型的数据类型转换成byte[]类型 
    7.    */  
    8.    public static final byte[] int2byte(int paramInt){  
    9.       byte[] resultByte = new byte[4];  
    10.       resultByte[3] = ((byte)(paramInt & 0xFF));  
    11.       resultByte[2] = ((byte)(paramInt >>> 8 & 0xFF));  
    12.       resultByte[1] = ((byte)(paramInt >>> 16 & 0xFF));  
    13.       resultByte[0] = ((byte)(paramInt >>> 24 & 0xFF));  
    14.   
    15.       return resultByte;  
    16.    }  
    17.   
    18.    /** 
    19.     * 将byte型的数据类型转换成int类型 
    20.    */  
    21.    public static final int getint(byte[] paramArrayOfByte){  
    22.       int result = (paramArrayOfByte[0] & 0xFF) << 24 | (paramArrayOfByte[1] & 0xFF) << 16 | (paramArrayOfByte[2] & 0xFF) << 8 | paramArrayOfByte[3] & 0xFF;  
    23.       return result;  
    24.    }  
    25.   
    26.    /** 
    27.     * 合并两个byte数组到一个byte数组中 
    28.    */  
    29.    public static byte[] byteMerge(byte[] byte1, byte[] byte2){  
    30.       byte[] result = new byte[byte1.length+byte2.length];  
    31.       System.arraycopy(byte1, 0, result, 0, byte1.length);  
    32.       System.arraycopy(byte2, 0, result, byte1.length, byte2.length);  
    33.       return result;  
    34.    }  
    35. }  



    http://blog.csdn.net/defonds/article/details/8782785

  • 相关阅读:
    实习小白::(转) 官网文档 -->> 骨骼动画详解-Spine
    实习小白::(转) 在cocos2d-x中使用CCArmature实现骨骼动画
    实习小白::(转) 骨骼动画 vs. 精灵表(sprite sheets)
    实习小白::(转) Cocos2d-x 更改文字换行风格 ( cocos2dx change line )
    实习小白::(转) Cocos2d-x 3.x 开发(十八)10行代码看自动Batch,10行代码看自动剔除 --------其实就是渲染图片机制
    实习小白::(转) Cocos2d-x 3.0 开发(十七)使用Cocos2d-x 3.0rc,一条命令打包Android
    实习小白::(转) Cocos2d-x 3.0 开发(十六)cocos2dx-3.0beta版建立新项目并加载CocoStudio导出文件
    实习小白::(转) Cocos2d-x 3.0 开发(十五)使用UILayout布局,制作对话界面
    实习小白::(转) Cocos2d-x 3.0 开发(十四)使用UIScrollView 实现大小不同物品拖动展示
    实习小白::(转) Cocos2d-x 3.0开发(十三)使用CocoStudio编辑帧事件并关联到程序
  • 原文地址:https://www.cnblogs.com/yhtboke/p/6230149.html
Copyright © 2020-2023  润新知