zoukankan      html  css  js  c++  java
  • SocketChannel 例子(转)

    Socket通信比较常见的问题有如下几种:
    1、设置收发超时;
    2、正确的每一个bit的收发;
    3、物理线路故障的保护;
    4、始终能正常工作;
    5、尽量少占系统资源;
    n、……
    而Socket编程有一个共性,尽管100个人可能会写出1000种实现,但做的事情却只有一种,就是:通信
    为此,通过学习dnsjava的通信代码,加上自己在一些项目中的实践,现在给出TCP通信的例子实现如下,希望能够给想偷懒的人一个简单的解决方案。
    本方案在正常的局域网连接中测试过几百万次没什么问题。缺乏更艰苦的环境,所以如果使用这些代码发生任何风险的话……
    (TcpChannel代码为Brian Wellington所做,原名为TCPClient,经本人稍作改动)
    Java代码
    1. // Copyright (c) 2005 Brian Wellington (bwelling@xbill.org)  
    2.   
    3. package asynchronizedchannel;  
    4.   
    5. import java.io.*;  
    6. import java.net.*;  
    7. import java.nio.*;  
    8. import java.nio.channels.*;  
    9.   
    10. final class TcpChannel  
    11. {  
    12.     private long endTime;  
    13.     private SelectionKey key;  
    14.   
    15.     public TcpChannel(SelectableChannel channel, long endTime, int op) throws IOException  
    16.     {  
    17.         boolean done = false;  
    18.         Selector selector = null;  
    19.         this.endTime = endTime;  
    20.         try {  
    21.             selector = Selector.open();  
    22.             channel.configureBlocking(false);  
    23.             key = channel.register(selector, op);  
    24.             done = true;  
    25.         } finally {  
    26.             if (!done && selector != null) {  
    27.                 selector.close();  
    28.             }  
    29.             if (!done) {  
    30.                 channel.close();  
    31.             }  
    32.         }  
    33.     }  
    34.   
    35.     static void blockUntil(SelectionKey key, long endTime) throws IOException  
    36.     {  
    37.         long timeout = endTime - System.currentTimeMillis();  
    38.         int nkeys = 0;  
    39.         if (timeout > 0) {  
    40.             nkeys = key.selector().select(timeout);  
    41.         } else if (timeout == 0) {  
    42.             nkeys = key.selector().selectNow();  
    43.         }  
    44.         if (nkeys == 0) {  
    45.             throw new SocketTimeoutException();  
    46.         }  
    47.     }  
    48.   
    49.     void cleanup()  
    50.     {  
    51.         try {  
    52.             key.selector().close();  
    53.             key.channel().close();  
    54.         } catch (IOException ex) {  
    55.             ex.printStackTrace();  
    56.         }  
    57.     }  
    58.   
    59.     void bind(SocketAddress addr) throws IOException  
    60.     {  
    61.         SocketChannel channel = (SocketChannel) key.channel();  
    62.         channel.socket().bind(addr);  
    63.     }  
    64.   
    65.     void connect(SocketAddress addr) throws IOException  
    66.     {  
    67.         SocketChannel channel = (SocketChannel) key.channel();  
    68.         if (channel.connect(addr))  
    69.             return;  
    70.         key.interestOps(SelectionKey.OP_CONNECT);  
    71.         try {  
    72.             while (!channel.finishConnect()) {  
    73.                 if (!key.isConnectable()) {  
    74.                     blockUntil(key, endTime);  
    75.                 }  
    76.             }  
    77.         } finally {  
    78.             if (key.isValid()) {  
    79.                 key.interestOps(0);  
    80.             }  
    81.         }  
    82.     }  
    83.   
    84.     void send(ByteBuffer buffer) throws IOException  
    85.     {  
    86.         Send.operate(key, buffer, endTime);  
    87.     }  
    88.   
    89.     void recv(ByteBuffer buffer) throws IOException  
    90.     {  
    91.         Recv.operate(key, buffer, endTime);  
    92.     }  
    93. }  
    94.   
    95. interface Operator  
    96. {  
    97.     class Operation  
    98.     {  
    99.         static void operate(final int op, final SelectionKey key, final ByteBuffer buffer, final long endTime, final Operator optr) throws IOException  
    100.         {  
    101.             final SocketChannel channel = (SocketChannel) key.channel();  
    102.             final int total = buffer.capacity();  
    103.             key.interestOps(op);  
    104.             try {  
    105.                 while (buffer.position() < total) {  
    106.                     if (System.currentTimeMillis() > endTime) {  
    107.                         throw new SocketTimeoutException();  
    108.                     }  
    109.                     if ((key.readyOps() & op) != 0) {  
    110.                         if (optr.io(channel, buffer) < 0) {  
    111.                             throw new EOFException();  
    112.                         }  
    113.                     } else {  
    114.                         TcpChannel.blockUntil(key, endTime);  
    115.                     }  
    116.                 }  
    117.             } finally {  
    118.                 if (key.isValid()) {  
    119.                     key.interestOps(0);  
    120.                 }  
    121.             }  
    122.         }  
    123.     }  
    124.   
    125.     int io(SocketChannel channel, ByteBuffer buffer) throws IOException;  
    126. }  
    127. class Send implements Operator  
    128. {  
    129.     public int io(SocketChannel channel, ByteBuffer buffer) throws IOException  
    130.     {  
    131.         return channel.write(buffer);  
    132.     }  
    133.     public static final void operate(final SelectionKey key, final ByteBuffer buffer, final long endTime) throws IOException  
    134.     {  
    135.         Operation.operate(SelectionKey.OP_WRITE, key, buffer, endTime, operator);  
    136.     }  
    137.     public static final Send operator = new Send();  
    138. }  
    139.   
    140. class Recv implements Operator  
    141. {  
    142.     public int io(SocketChannel channel, ByteBuffer buffer) throws IOException  
    143.     {  
    144.         return channel.read(buffer);  
    145.     }  
    146.       
    147.     public static final void operate(final SelectionKey key, final ByteBuffer buffer, final long endTime) throws IOException  
    148.     {  
    149.         Operation.operate(SelectionKey.OP_READ, key, buffer, endTime, operator);  
    150.     }  
    151.     public static final Recv operator = new Recv();  
    152. }  
    // Copyright (c) 2005 Brian Wellington (bwelling@xbill.org)  package asynchronizedchannel;  import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*;  final class TcpChannel {     private long endTime;     private SelectionKey key;      public TcpChannel(SelectableChannel channel, long endTime, int op) throws IOException     {         boolean done = false;         Selector selector = null;         this.endTime = endTime;         try {             selector = Selector.open();             channel.configureBlocking(false);             key = channel.register(selector, op);             done = true;         } finally {             if (!done && selector != null) {                 selector.close();             }             if (!done) {                 channel.close();             }         }     }      static void blockUntil(SelectionKey key, long endTime) throws IOException     {         long timeout = endTime - System.currentTimeMillis();         int nkeys = 0;         if (timeout > 0) {             nkeys = key.selector().select(timeout);         } else if (timeout == 0) {             nkeys = key.selector().selectNow();         }         if (nkeys == 0) {             throw new SocketTimeoutException();         }     }      void cleanup()     {         try {             key.selector().close();             key.channel().close();         } catch (IOException ex) {             ex.printStackTrace();         }     }      void bind(SocketAddress addr) throws IOException     {         SocketChannel channel = (SocketChannel) key.channel();         channel.socket().bind(addr);     }      void connect(SocketAddress addr) throws IOException     {         SocketChannel channel = (SocketChannel) key.channel();         if (channel.connect(addr))             return;         key.interestOps(SelectionKey.OP_CONNECT);         try {             while (!channel.finishConnect()) {                 if (!key.isConnectable()) {                     blockUntil(key, endTime);                 }             }         } finally {             if (key.isValid()) {                 key.interestOps(0);             }         }     }      void send(ByteBuffer buffer) throws IOException     {         Send.operate(key, buffer, endTime);     }      void recv(ByteBuffer buffer) throws IOException     {         Recv.operate(key, buffer, endTime);     } }  interface Operator {     class Operation     {         static void operate(final int op, final SelectionKey key, final ByteBuffer buffer, final long endTime, final Operator optr) throws IOException         {             final SocketChannel channel = (SocketChannel) key.channel();             final int total = buffer.capacity();             key.interestOps(op);             try {                 while (buffer.position() < total) {                     if (System.currentTimeMillis() > endTime) {                         throw new SocketTimeoutException();                     }                     if ((key.readyOps() & op) != 0) {                         if (optr.io(channel, buffer) < 0) {                             throw new EOFException();                         }                     } else {                         TcpChannel.blockUntil(key, endTime);                     }                 }             } finally {                 if (key.isValid()) {                     key.interestOps(0);                 }             }         }     }      int io(SocketChannel channel, ByteBuffer buffer) throws IOException; } class Send implements Operator {     public int io(SocketChannel channel, ByteBuffer buffer) throws IOException     {         return channel.write(buffer);     }     public static final void operate(final SelectionKey key, final ByteBuffer buffer, final long endTime) throws IOException     {         Operation.operate(SelectionKey.OP_WRITE, key, buffer, endTime, operator);     }     public static final Send operator = new Send(); }  class Recv implements Operator {     public int io(SocketChannel channel, ByteBuffer buffer) throws IOException     {         return channel.read(buffer);     }          public static final void operate(final SelectionKey key, final ByteBuffer buffer, final long endTime) throws IOException     {         Operation.operate(SelectionKey.OP_READ, key, buffer, endTime, operator);     }     public static final Recv operator = new Recv(); } 

    使用演示见以下代码。
    大致说明一下,Server端开5656侦听,Client端开若干线程测试Socket通信。每次发送240字节信息+16字节MD5校验。服务端收到信息之后做MD5检查,正确的,发送“.xxxx”表示认可,否则发送“?xxxx”表示故障。
    正式应用中可以再设置tryout尝试n次。
    Server端,代码演示:
    Java代码
    1. package asynchronizedchannel;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.InetSocketAddress;  
    5. import java.nio.ByteBuffer;  
    6. import java.nio.channels.SelectionKey;  
    7. import java.nio.channels.Selector;  
    8. import java.nio.channels.ServerSocketChannel;  
    9. import java.nio.channels.SocketChannel;  
    10. import java.security.MessageDigest;  
    11. import java.util.Iterator;  
    12.   
    13. public class Server  
    14. {  
    15.   
    16.     /** 
    17.      * 服务端通信范例程序主函数 
    18.      *  
    19.      * @param args 
    20.      * @throws IOException 
    21.      */  
    22.     public static void main(String[] args) throws IOException  
    23.     {  
    24.         // Create the selector  
    25.         final Selector selector = Selector.open();  
    26.         final ServerSocketChannel server = ServerSocketChannel.open();  
    27.         server.configureBlocking(false);  
    28.         server.socket().bind(new InetSocketAddress("xx.xx.xx.xx", 5656), 5);  
    29.         // Register both channels with selector  
    30.         server.register(selector, SelectionKey.OP_ACCEPT);  
    31.         new Thread(new Daemon(selector)).start();  
    32.     }  
    33. }  
    34.   
    35. class Daemon implements Runnable  
    36. {  
    37.     private final Selector selector;  
    38.   
    39.     Daemon(Selector selector)  
    40.     {  
    41.         this.selector = selector;  
    42.     }  
    43.   
    44.     public void run()  
    45.     {  
    46.         while (true) {  
    47.             try {  
    48.                 // Wait for an event  
    49.                 selector.select();  
    50.   
    51.                 // Get list of selection keys with pending events  
    52.                 Iterator<SelectionKey> it = selector.selectedKeys().iterator();  
    53.   
    54.                 // Process each key  
    55.                 while (it.hasNext()) {  
    56.                     // Get the selection key  
    57.                     SelectionKey selKey = it.next();  
    58.   
    59.                     // Remove it from the list to indicate that it is being processed  
    60.                     it.remove();  
    61.   
    62.                     // Check if it's a connection request  
    63.                     if (selKey.isAcceptable()) {  
    64.                         // Get channel with connection request  
    65.                         ServerSocketChannel server = (ServerSocketChannel) selKey.channel();  
    66.                         // Accept the connection request.  
    67.                         // If serverSocketChannel is blocking, this method blocks.  
    68.                         // The returned channel is in blocking mode.  
    69.                         SocketChannel channel = server.accept();  
    70.   
    71.                         // If serverSocketChannel is non-blocking, sChannel may be null  
    72.                         if (channel != null) {  
    73.                             // Use the socket channel to communicate with the client  
    74.                             new Thread(new ServerHandler(channel)).start();  
    75.                         } else {  
    76.                             System.out.println("---No Connection---");  
    77.                             // There were no pending connection requests; try again later.  
    78.                             // To be notified of connection requests,  
    79.                         }  
    80.                     }  
    81.                 }  
    82.             } catch (Exception ex) {  
    83.                 ex.printStackTrace();  
    84.             }  
    85.         }  
    86.     }  
    87. }  
    88.   
    89. class ServerHandler implements Runnable  
    90. {  
    91.     private static final long timeout = 30 * 1000; // 设置超时时间为30秒  
    92.     private static int counter = 0;  
    93.     private final TcpChannel channel;  
    94.     private final MessageDigest md;  
    95.   
    96.     ServerHandler(SocketChannel channel) throws Exception  
    97.     {  
    98.         this.channel = new TcpChannel(channel, System.currentTimeMillis() + timeout, SelectionKey.OP_READ);  
    99.         md = MessageDigest.getInstance("md5");  
    100.     }  
    101.   
    102.     public void run()  
    103.     {  
    104.         try {  
    105.             while (true) {  
    106.                 work();  
    107.                 synchronized (ServerHandler.class) {  
    108.                     if ((++counter & 65535) == 0) {  
    109.                         System.out.println(counter);  
    110.                     }  
    111.                 }  
    112.             }  
    113.         } catch (Exception e) {  
    114.             e.printStackTrace();  
    115.         } finally {  
    116.             channel.cleanup();  
    117.         }  
    118.     }  
    119.   
    120.     private void work() throws IOException  
    121.     { // 模拟工作流程  
    122.         byte[] cache = new byte[256], reply = new byte[5];  
    123.         read(cache, reply);  
    124.     }  
    125.   
    126.     private void read(byte[] cache, byte[] reply) throws IOException  
    127.     { // 从套接字读入数据  
    128.         channel.recv(ByteBuffer.wrap(cache));  
    129.         md.reset();  
    130.         md.update(cache, 0, 240);  
    131.         byte[] md5 = md.digest(); // 使用前240字节产生MD5校验码  
    132.         if (!ExtArrays.partialEquals(md5, 0, cache, 240, 16)) { // 与后16字节比较  
    133.             reply[0] = '?';  
    134.             System.out.println("MISMATCH!");  
    135.         } else {  
    136.             reply[0] = '.';  
    137.         }  
    138.         channel.send(ByteBuffer.wrap(reply)); // 返回接收结果  
    139.     }  
    140. }  
    141.   
    142. final class ExtArrays  
    143. {  
    144.     private ExtArrays()  
    145.     {  
    146.     }  
    147.   
    148.     public static boolean partialEquals(byte[] a, int offset_a, byte[] b, int offset_b, int len)  
    149.     { // 字节数组的部分比较  
    150.         if (a == null || b == null) {  
    151.             return false;  
    152.         }  
    153.         if (offset_a + len > a.length || offset_b + len > b.length) {  
    154.             return false;  
    155.         }  
    156.         for (int i = offset_a, j = offset_b, k = len; k > 0; i++, j++, k--) {  
    157.             if (a[i] != b[j]) {  
    158.                 return false;  
    159.             }  
    160.         }  
    161.         return true;  
    162.     }  
    163. }  
    package asynchronizedchannel;  import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.security.MessageDigest; import java.util.Iterator;  public class Server {      /**      * 服务端通信范例程序主函数      *       * @param args      * @throws IOException      */     public static void main(String[] args) throws IOException     {         // Create the selector         final Selector selector = Selector.open();         final ServerSocketChannel server = ServerSocketChannel.open();         server.configureBlocking(false);         server.socket().bind(new InetSocketAddress("xx.xx.xx.xx", 5656), 5);         // Register both channels with selector         server.register(selector, SelectionKey.OP_ACCEPT);         new Thread(new Daemon(selector)).start();     } }  class Daemon implements Runnable {     private final Selector selector;      Daemon(Selector selector)     {         this.selector = selector;     }      public void run()     {         while (true) {             try {                 // Wait for an event                 selector.select();                  // Get list of selection keys with pending events                 Iterator<SelectionKey> it = selector.selectedKeys().iterator();                  // Process each key                 while (it.hasNext()) {                     // Get the selection key                     SelectionKey selKey = it.next();                      // Remove it from the list to indicate that it is being processed                     it.remove();                      // Check if it's a connection request                     if (selKey.isAcceptable()) {                         // Get channel with connection request                         ServerSocketChannel server = (ServerSocketChannel) selKey.channel();                         // Accept the connection request.                         // If serverSocketChannel is blocking, this method blocks.                         // The returned channel is in blocking mode.                         SocketChannel channel = server.accept();                          // If serverSocketChannel is non-blocking, sChannel may be null                         if (channel != null) {                             // Use the socket channel to communicate with the client                             new Thread(new ServerHandler(channel)).start();                         } else {                             System.out.println("---No Connection---");                             // There were no pending connection requests; try again later.                             // To be notified of connection requests,                         }                     }                 }             } catch (Exception ex) {                 ex.printStackTrace();             }         }     } }  class ServerHandler implements Runnable {     private static final long timeout = 30 * 1000; // 设置超时时间为30秒     private static int counter = 0;     private final TcpChannel channel;     private final MessageDigest md;      ServerHandler(SocketChannel channel) throws Exception     {         this.channel = new TcpChannel(channel, System.currentTimeMillis() + timeout, SelectionKey.OP_READ);         md = MessageDigest.getInstance("md5");     }      public void run()     {         try {             while (true) {                 work();                 synchronized (ServerHandler.class) {                     if ((++counter & 65535) == 0) {                         System.out.println(counter);                     }                 }             }         } catch (Exception e) {             e.printStackTrace();         } finally {             channel.cleanup();         }     }      private void work() throws IOException     { // 模拟工作流程         byte[] cache = new byte[256], reply = new byte[5];         read(cache, reply);     }      private void read(byte[] cache, byte[] reply) throws IOException     { // 从套接字读入数据         channel.recv(ByteBuffer.wrap(cache));         md.reset();         md.update(cache, 0, 240);         byte[] md5 = md.digest(); // 使用前240字节产生MD5校验码         if (!ExtArrays.partialEquals(md5, 0, cache, 240, 16)) { // 与后16字节比较             reply[0] = '?';             System.out.println("MISMATCH!");         } else {             reply[0] = '.';         }         channel.send(ByteBuffer.wrap(reply)); // 返回接收结果     } }  final class ExtArrays {     private ExtArrays()     {     }      public static boolean partialEquals(byte[] a, int offset_a, byte[] b, int offset_b, int len)     { // 字节数组的部分比较         if (a == null || b == null) {             return false;         }         if (offset_a + len > a.length || offset_b + len > b.length) {             return false;         }         for (int i = offset_a, j = offset_b, k = len; k > 0; i++, j++, k--) {             if (a[i] != b[j]) {                 return false;             }         }         return true;     } } 

    Client端,代码演示:
    Java代码
    1. package asynchronizedchannel;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.InetSocketAddress;  
    5. import java.nio.ByteBuffer;  
    6. import java.nio.channels.SelectionKey;  
    7. import java.nio.channels.SocketChannel;  
    8. import java.security.DigestException;  
    9. import java.security.MessageDigest;  
    10. import java.util.Random;  
    11.   
    12. public class Client  
    13. {  
    14.     private static int id = 0;  
    15.     /** 
    16.      * 客户端通信范例程序主函数 
    17.      *  
    18.      * @param args 
    19.      * @throws Exception 
    20.      */  
    21.     public static void main(String[] args) throws Exception  
    22.     {  
    23.         new Thread(new ClientHandler(id++)).start();  
    24.         new Thread(new ClientHandler(id++)).start();  
    25.         new Thread(new ClientHandler(id++)).start();  
    26.         new Thread(new ClientHandler(id++)).start();  
    27.         new Thread(new ClientHandler(id++)).start();  
    28.     }  
    29.   
    30. }  
    31.   
    32. class ClientHandler implements Runnable  
    33. {  
    34.     private static final long timeout = 30 * 1000; // 设置超时时间为30秒  
    35.     private final TcpChannel channel;  
    36.       
    37.     private final int id;  
    38.   
    39.     private final MessageDigest md;  
    40.     private final Random rand;  
    41.   
    42.     ClientHandler(int id) throws Exception  
    43.     {  
    44.         this.id = id;  
    45.         channel = new TcpChannel(SocketChannel.open(), System.currentTimeMillis() + timeout, SelectionKey.OP_WRITE);  
    46.         md = MessageDigest.getInstance("md5");  
    47.         rand = new Random();  
    48.     }  
    49.   
    50.     @Override  
    51.     public void run()  
    52.     {  
    53.         try {  
    54.             channel.connect(new InetSocketAddress("xx.xx.xx.xx", 5656));  
    55.             int i = 0;  
    56.             while (true) {  
    57.                 work();  
    58.                 if ((++i & 16383) == 0) {  
    59.                     System.out.println(String.format("client(%1$d): %2$d", id, i));  
    60.                 }  
    61.                 Thread.yield();  
    62.             }  
    63.         } catch (Exception e) {  
    64.             e.printStackTrace();  
    65.         } finally {  
    66.             channel.cleanup();  
    67.         }  
    68.     }  
    69.   
    70.     private void work() throws IOException, DigestException  
    71.     {  
    72.         byte[] cache = new byte[256], reply = new byte[5];  
    73.         write(cache, reply);  
    74.     }  
    75.   
    76.     private void write(byte[] cache, byte[] reply) throws DigestException, IOException  
    77.     {  
    78.         rand.nextBytes(cache); // 只用前面的240字节  
    79.         md.reset();  
    80.         md.update(cache, 0, 240);  
    81.         md.digest(cache, 240, 16); // MD5校验码占后面16字节  
    82.         ByteBuffer buffer = ByteBuffer.wrap(cache);  
    83.         channel.send(buffer);  
    84.         buffer = ByteBuffer.wrap(reply);  
    85.         channel.recv(buffer);  
    86.         if (reply[0] != '.') { // 若接收的结果不正确,可以考虑尝试再次发送  
    87.             System.out.println("MISMATCH!");  
    88.         }  
    89.     }  
    90. }  
    package asynchronizedchannel;  import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.security.DigestException; import java.security.MessageDigest; import java.util.Random;  public class Client {     private static int id = 0;     /**      * 客户端通信范例程序主函数      *       * @param args      * @throws Exception      */     public static void main(String[] args) throws Exception     {         new Thread(new ClientHandler(id++)).start();         new Thread(new ClientHandler(id++)).start();         new Thread(new ClientHandler(id++)).start();         new Thread(new ClientHandler(id++)).start();         new Thread(new ClientHandler(id++)).start();     }  }  class ClientHandler implements Runnable {     private static final long timeout = 30 * 1000; // 设置超时时间为30秒     private final TcpChannel channel;          private final int id;      private final MessageDigest md;     private final Random rand;      ClientHandler(int id) throws Exception     {         this.id = id;         channel = new TcpChannel(SocketChannel.open(), System.currentTimeMillis() + timeout, SelectionKey.OP_WRITE);         md = MessageDigest.getInstance("md5");         rand = new Random();     }      @Override     public void run()     {         try {             channel.connect(new InetSocketAddress("xx.xx.xx.xx", 5656));             int i = 0;             while (true) {                 work();                 if ((++i & 16383) == 0) {                     System.out.println(String.format("client(%1$d): %2$d", id, i));                 }                 Thread.yield();             }         } catch (Exception e) {             e.printStackTrace();         } finally {             channel.cleanup();         }     }      private void work() throws IOException, DigestException     {         byte[] cache = new byte[256], reply = new byte[5];         write(cache, reply);     }      private void write(byte[] cache, byte[] reply) throws DigestException, IOException     {         rand.nextBytes(cache); // 只用前面的240字节         md.reset();         md.update(cache, 0, 240);         md.digest(cache, 240, 16); // MD5校验码占后面16字节         ByteBuffer buffer = ByteBuffer.wrap(cache);         channel.send(buffer);         buffer = ByteBuffer.wrap(reply);         channel.recv(buffer);         if (reply[0] != '.') { // 若接收的结果不正确,可以考虑尝试再次发送             System.out.println("MISMATCH!");         }     } } 

    重点说明:

    发多少,收多少。要么固定发送和接收的字节数,要么在发送的时候带有发送字节数的信息,接收的时候根据该信息接收完整然后再处理。

     转http://regular.javaeye.com/blog/653936

  • 相关阅读:
    【翻译/介绍】jump consistent hash:零内存消耗,均匀,快速,简洁,来自Google的一致性哈希算法 [2015-03-13]
    现代密码学实践指南[2015年]
    本博客迁走了
    高性能web系统的架构和系统优化
    vs 2013调试的时候重启的解决方案
    年会与项目管理
    javascript 关闭窗口,弹出新窗口并带有确认关闭对话框解决办法
    成长
    POCO exception
    通过OpenGL ES在iOS平台实践增强现实(二)
  • 原文地址:https://www.cnblogs.com/likwo/p/1768411.html
Copyright © 2011-2022 走看看