随笔-159  评论-114  文章-7  trackbacks-0

flash 的socket 真不错,什么事都内部给办了,换了java,有些麻烦。

网上那些nio的例子简单到无实际价值。

ByteBuffer totalReceiveBuff = ByteBuffer.allocate(30000);

..


private void newParseSocketData(int remainSize,SelectionKey key) throws IOException {
        
if (remainSize == 0)
            totalReceiveBuff.clear();
        
int firstReadSize = remainSize;
        
while(true)
        
{
            
if(key.isReadable())
            
{
                firstReadSize 
+= sc.read(totalReceiveBuff);
                
break;
            }

            
try {
                Thread.sleep(
200);
            }
 catch (InterruptedException e) {
                
// TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        
if (firstReadSize < 8{
            System.out.println(firstReadSize 
+ "sssss");
            
return;
        }

        totalReceiveBuff.flip();
        
if (totalReceiveBuff.getInt() != 开始标识) {
            
return;
        }


        
int msgLength = totalReceiveBuff.getInt();

        
if (totalReceiveBuff.remaining() < msgLength + 4{
            
int hasReadSize = firstReadSize;
            
int totalSize = msgLength + 12;
            totalReceiveBuff.position(totalReceiveBuff.limit());
            totalReceiveBuff.limit(totalReceiveBuff.capacity());
            
while (true{
                
int currentLoopReadSize = sc.read(totalReceiveBuff);
                hasReadSize 
+= currentLoopReadSize;
                
if (hasReadSize >= totalSize) {
                    
break;
                }
 else {
                    
continue;
                }

            }

            totalReceiveBuff.flip();
            
if (totalReceiveBuff.getInt() != 开始标识) {
                
return;
            }

            
int size = totalReceiveBuff.getInt();
            
byte[] bytes = new byte[size];
            totalReceiveBuff.get(bytes);
            
if (totalReceiveBuff.getInt() != 结束标识) {
                
return;
            }

            ByteBuffer realContentBuff 
= ByteBuffer.wrap(bytes);
            
int contentRealSize = realContentBuff.getShort();

            
byte[] stringBytes = new byte[contentRealSize];
            realContentBuff.get(stringBytes);
            handleServerCommand(
new String(stringBytes, "UTF-8"));
        }
 else {
            
byte[] bytes = new byte[msgLength];
            totalReceiveBuff.get(bytes);
            
if (totalReceiveBuff.getInt() != 结束标识) {
                
return;
            }

            ByteBuffer realContentBuff 
= ByteBuffer.wrap(bytes);
            
int contentRealSize = realContentBuff.getShort();

            
byte[] stringBytes = new byte[contentRealSize];
            realContentBuff.get(stringBytes);
            handleServerCommand(
new String(stringBytes, "UTF-8"));
        }


        
// handle remain need to read
        if (totalReceiveBuff.hasRemaining()) {
            
byte[] remainBytes = new byte[totalReceiveBuff.remaining()];
            totalReceiveBuff.get(remainBytes);
            totalReceiveBuff.clear();
            totalReceiveBuff.put(remainBytes);

            newParseSocketData(remainBytes.length,key);
        }
 else {
            totalReceiveBuff.clear();
            
if(key.isReadable())
            
{
                
int pendingcounter = 0;
                
int available = 0;
                
while((pendingcounter++ < 20))
                
{                    
                    available 
= sc.read(totalReceiveBuff);
                    
if (available <= 0)
                    
{
                        
try {
                            Thread.sleep(
100);
                        }
 catch (InterruptedException e) {
                            
// TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                        
continue;
                    }

                    
else
                    
{
                        newParseSocketData(available,key);
                        
break;
                    }

                }

                
            }

        }


    }


在网络不好的情况,其实你无法保证一次读到的信息就是你要的那个正好的大小,你需要对于数据包进行积累,或者多读了,需要继续处理下次从socket读到的剩余信息。

而flash 比较简单

public function parseSocketData()
        
{
            
if(this.socketEchoSize==0){
                
if (socket.bytesAvailable < 8return;
                
//包头标志
                if(socket.readInt()!=开始标识){
                    var bytes:ByteArray
=new ByteArray();
                    socket.readBytes(bytes,
0,socket.bytesAvailable);
                    
this.socketEchoSize=0;
                    
return;
                }

                
this.socketEchoSize=socket.readInt();
            }

            
//trace(socket.bytesAvailable, this.socketEchoSize);
            
//如果长度不够就攒下来
            if (socket.bytesAvailable < this.socketEchoSize + 4)
            
{
                
//socket.readShort();
                
//trace("data lost in transport:\n", socket.readUTFBytes(socket.bytesAvailable));
                return;
            }

            var buffer : ByteArray 
= new ByteArray();
            socket.readBytes(buffer, 
0this.socketEchoSize);
            
//包尾标志
            if (socket.readInt() == 结束标识)
            
{
                var sx:String 
= buffer.readUTFBytes(buffer.readShort());
                
//trace("received:\n" + sx);
                this.receive(sx);
            }

            
this.socketEchoSize=0;
            
if(socket.bytesAvailable>0){
                
this.parseSocketData();
            }

        }

人家flash的socket自己下面就帮你不断的读着,你每次之需要判断byteAvailable属性大于0否,就ok了。

java  ,严谨。都需要在byteBuffer上面坐判断。




最正确的写法:

private void newParseSocketData() throws IOException {
        
int count = 1;
        
int byteRead = 0;

        Selector readSelector 
= null;
        SelectionKey tmpKey 
= null;

        
try{
            
while (count > 0{
                count 
= sc.read(totalReceiveBuff); // [1]
                if (count > -1)
                
{
                    byteRead 
+= count;
                    
                }
                    
            }


            
if (byteRead == 0{
                readSelector 
= Selector.open();
                count 
= 1;
                
                tmpKey 
= sc.register(readSelector, SelectionKey.OP_READ);
    
                tmpKey.interestOps(tmpKey.interestOps() 
| SelectionKey.OP_READ);
    
                
int code = readSelector.select(200); // [3]
    
                tmpKey.interestOps(
    
                tmpKey.interestOps() 
& (~SelectionKey.OP_READ));
    
                
if (code == 0{
    
                    
return// Return on the main Selector and try again.
    
                }

    
                
while (count > 0 ) {
    
                    count 
= sc.read(totalReceiveBuff); // [4]
    
                    
if (count > -1)
                    
{
                        byteRead 
+= count;
                    }

                    
                }

    
            }

        }
finally
        
{
            
if (tmpKey != null)

                tmpKey.cancel();

            
if (readSelector != null){

                
try{
                    readSelector.selectNow();

                }
 catch (IOException ex){
                    ;
                }

                readSelector.close();
            }

        }


        totalReceiveBuff.flip();
        
        
while (totalReceiveBuff.remaining() > 8{

            
if (totalReceiveBuff.getInt() != 592464711{
                
return;
            }

            
int size = totalReceiveBuff.getInt();
            
if (totalReceiveBuff.remaining() < size + 4{
                
int hasReadSize = byteRead;
                
int totalSize = size + 12;
                totalReceiveBuff.position(totalReceiveBuff.limit());
                totalReceiveBuff.limit(totalReceiveBuff.capacity());
                
while (true{
                    
int currentLoopReadSize = sc.read(totalReceiveBuff);
                    hasReadSize 
+= currentLoopReadSize;
                    
if (hasReadSize >= totalSize) {
                        
break;
                    }
 else {
                        
continue;
                    }

                }

                totalReceiveBuff.flip();
                
if (totalReceiveBuff.getInt() != 592464711{
                    
return;
                }

                
int msgLength = totalReceiveBuff.getInt();
                
byte[] bytes = new byte[msgLength];
                totalReceiveBuff.get(bytes);
                
if (totalReceiveBuff.getInt() != 1347110691{
                    
return;
                }

                ByteBuffer realContentBuff 
= ByteBuffer.wrap(bytes);
                
int contentRealSize = realContentBuff.getShort();

                
byte[] stringBytes = new byte[contentRealSize];
                realContentBuff.get(stringBytes);
                handleServerCommand(
new String(stringBytes, "UTF-8"));
            }

            
else
            
{
    
                
byte[] bytes = new byte[size];
                totalReceiveBuff.get(bytes);
                
if (totalReceiveBuff.getInt() != 1347110691{
                    
return;
                }

                ByteBuffer realContentBuff 
= ByteBuffer.wrap(bytes);
                
int contentRealSize = realContentBuff.getShort();
    
                
byte[] stringBytes = new byte[contentRealSize];
                realContentBuff.get(stringBytes);
                handleServerCommand(
new String(stringBytes, "UTF-8"));
            }


        }


        totalReceiveBuff.clear();    

    }






posted on 2008-11-04 15:14 北国狼人的BloG 阅读(451) 评论(1)  编辑  收藏

评论:
# re: 如何使用NIO 分次读取信息 攒包 2009-02-11 13:59 | zkp
我想问,FLash的Socket也是NIO吗?  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: