zoukankan      html  css  js  c++  java
  • javaSocket与C通信

    前段时间写了个web端与C服务端之间的通信不过用的是短连接 非堵塞的方式,一直想使用长连接,使tomcat启动的时候就和C服务端进行通信,但是一直没找到方法希望je的朋友能给点思路。先来看我现在的具体实现 
    通信的核心类
    public   class  newsSockBase    
    {   
         private  SocketChannel sc;     
         private   final   int  MAX_LENGTH =  8192 ;     
         private  ByteBuffer r_buff ;     
         private  ByteBuffer w_buff ;     
         private   static  String host ;     
         private   static   int  port;     
      
         int      sendBufTotalLen;   
         int      sendBufLen;   
         int      sendBufStart;   
         byte []  sendBuf;   
           
         int      recvBufTotalLen;   
         int      recvBufLen;   
         int      recvBufStart;   
         byte []  recvBuf;   
           
         int      timeout;   
        String  msg;   
           
         public  newsSockBase()   
        {   
            r_buff = ByteBuffer.allocate(MAX_LENGTH);     
            w_buff = ByteBuffer.allocate(MAX_LENGTH);    
               
            sendBufTotalLen = MAX_LENGTH;   
            sendBufLen = sendBufStart =  0 ;   
            sendBuf =  new   byte [MAX_LENGTH];   
               
            recvBufTotalLen = MAX_LENGTH;   
            recvBufLen = recvBufStart =  0 ;   
            recvBuf =  new   byte [MAX_LENGTH];   
               
            timeout =  6 ;   
        }   
           
         public   void  setIPandPort(String str, int  pt)   
        {   
            host = str;   
            port  = pt;   
        }   
           
         //这两个函数一定要注意 形参是基类 而实际传入的参数是子类,到时候也是调用子类的参数来做    
         public   void  getBufFrompara(InewsDetail nD)   
        {   
             int  len = nD.encode(sendBuf, sendBufStart, sendBufTotalLen-sendBufStart-sendBufLen);   
               
            sendBufLen += len;   
               
        }   
           
         public   int  decodeBufToPara(InewsDetail nD)   
        {   
             int  len = nD.decode(recvBuf, recvBufStart, recvBufLen);   
             if  (len> 0 )    //解码正确的时候才做    
            {   
                recvBufLen -= len;   
                recvBufStart += len;           
            }   
               
             return  len;    
        }   
           
         public   void  start(InewsDetail nD)   
        {       
           
             //这里需要先根据传入的参数来    
            getBufFrompara(nD);   
               
             try  {     
                InetSocketAddress addr =  new  InetSocketAddress(host, port);     
                 // 生成一个socketchannel      
                sc = SocketChannel.open();     
                sc.configureBlocking( false ); //     
                 // 连接到server      
                sc.connect(addr);     
                 while  (!sc.finishConnect())     
                    ;     
                System.out.println( "connection has been established!…" );     
      
                // while (true)     
                {     
                     // 回射消息    // 复位,清空                
                    w_buff.clear();     
                    w_buff.put(sendBuf,sendBufStart,sendBufLen);     
                    w_buff.flip();    // 转到最开始     
      
      
                     // 发送消息      
                     while  (w_buff.hasRemaining())     
                        sc.write(w_buff);     
                    w_buff.clear();     
      
                     // 进入接收状态     
                     while  ( true )   
                    {   
                         int  ss= 0 ;   
                         int  count;     
                        r_buff.clear();    
                         while (ss<timeout* 100 )   
                        {                           
                            count = sc.read(r_buff);   
                             if  (count> 0 )   
                                 break ;   
                            ss++;   
                            Thread.currentThread().sleep( 10 );    
                        }     
                           
                         if  (ss==timeout)   
                        {   
                             break ;   
                        }   
                           
                        r_buff.flip();     
                           
                         //判断recvBuf能不能放下接收到的数据    
                         if  (r_buff.limit()+recvBufStart+recvBufLen>recvBufTotalLen)   
                        {   
                             //放不下了    
                             //那就先看看前面是不是有空余    
                             if  (recvBufStart> 0 )   
                            {   
                                 for ( int  i= 0 ;i<recvBufStart;i++)   
                                {   
                                    recvBuf  = recvBuf[i+recvBufStart];   
                                }   
                                recvBufStart = 0;   
      
                            }   
                               
                            if (r_buff.limit()+recvBufStart+recvBufLen>recvBufTotalLen)   
                            {   
                                //这个时候就是真的说数据区长度不够了,属于致命错误   
                                System.err.println("致命错误! 缓冲区长度过小!");   
                            }   
                        }   
                        else  
                        {   // 也可以转化为字符串,不过需要借助第三个变量了。    
                               
                            r_buff.get(recvBuf,recvBufStart+recvBufLen,r_buff.limit());   
                            //得到了一次数据就要试着做一次解码,如果能够解码,那就完成解码,不能则表示数据不完整,继续等待新数据   
                            //这里注意返回值 如果是0  表示数据不完整 如果是正数 就是解码的字节数 负数表示解码出错   
                            recvBufLen += r_buff.limit();   
                            if (decodeBufToPara(nD)!=0)   
                                break;   
                        }   
                            
                        System.out.println("reply is " + r_buff.limit() + " long " );     
                    }   
                }     
                sc.socket().close();   
                   
            } catch (IOException ioe) {     
                ioe.printStackTrace();     
            } catch (InterruptedException ie) {     
                ie.printStackTrace();     
            }     
               
            System.out.println("Exit App....... " );    
        }   
      
        public static void main(String[] args)    
        {   
            newsDetailNewsSum nDNS = new newsDetailNewsSum();   
            newsSockBase nsb = new newsSockBase();   
            nsb.setIPandPort("192.168.0.106",8888);   
            nsb.start(nDNS);   
               
            System.out.println("Exit Allllll....... " );   
        }   
      
    }  
    下面是报文协议的基类
    //此类试图将所有的通讯协议的编解码都包含在内!按照一次交互的过程来区分   
    public class newsDetail implements InewsDetail   
    {   
        protected int       netErr; //用来表示是不是网络出错了,主要是超时。这个时候就不需要检查其他参数了。   
        protected int       type;   //就是对应具体的操作类型码   
        protected byte[]    StreamID=new byte[16];  //对应具体的流水号   
        protected byte[]    asyn = new byte[2];   
           
        //这个还是有问题 不能达到预计效果 需要修改   
        static private int  seq=0;  //生成流水号后2位的时候使用的   
        static private Calendar lastCa;   
           
        public newsDetail()    
        {   
            getStreamID();   
        }   
           
           
           
        public int getType() {   
            return type;   
        }   
      
      
      
        public void setType(int type) {   
            this.type = type;   
        }   
      
      
      
        //基类中的编解码函数没有作用,具体使用的编解码函数在各个子类中需要重新实现   
        //必须有返回值 因为调用者需要根据返回值做一些操作   
        //这里的参数 buf是需要填写的缓冲区  start 是缓冲区开始位置 len 是可用的缓冲区长度   
        public int encode(byte[] buf,int start,int len)   
        {   
            return 0;   
        }   
        //这里的参数 buf是需要需要解码的缓冲区  start 是缓冲区开始位置 len 是需要解码的长度   
        public int decode(byte[] buf,int start,int len)   
        {   
            return 0;   
        }   
      
        public void getStreamID()   
        {   
            Calendar ca = Calendar.getInstance();   
              int year = ca.get(Calendar.YEAR);//获取年份   
              int month=ca.get(Calendar.MONTH)+1;//获取月份    
              int day=ca.get(Calendar.DATE);//获取日   
              int minute=ca.get(Calendar.MINUTE);//分    
              int hour=ca.get(Calendar.HOUR);//小时    
              int second=ca.get(Calendar.SECOND);//秒   
              int am_pm=ca.get(Calendar.AM_PM);   
              if (am_pm==Calendar.PM)   
                  hour += 12;   
              if (hour>=24)   
                  hour -= 24;   
                 
            System.out.println(seq);   
                  
              if (lastCa!=ca)   
              {   
                  lastCa = ca;   
                  seq = 12;   
              }   
              else  
              {   
                  seq++;   
                  if (seq>=100)   
                      seq = 0;   
              }   
                 
              //现在根据上面的字段组成StreamID字符串   
              //目前先使用手工的办法来写,效率高一些        
              StreamID[0] = (byte)(year/1000+'0');   
              StreamID[1] = (byte)((year-(StreamID[0]-'0')*1000)/100+'0');   
              StreamID[2] = (byte)((year-(StreamID[0]-'0')*1000-(StreamID[1]-'0')*100)/10+'0');   
              StreamID[3] = (byte)(year-(StreamID[0]-'0')*1000-(StreamID[1]-'0')*100-(StreamID[2]-'0')*10+'0');   
                 
              StreamID[4] = (byte)(month/10+'0');   
              StreamID[5] = (byte)((month-(StreamID[4]-'0')*10)+'0');   
                 
              StreamID[6] = (byte)(day/10+'0');   
              StreamID[7] = (byte)((day-(StreamID[6]-'0')*10)+'0');   
                 
              StreamID[8] = (byte)(hour/10+'0');   
              StreamID[9] = (byte)((hour-(StreamID[8]-'0')*10)+'0');   
                 
              StreamID[10] = (byte)(minute/10+'0');   
              StreamID[11] = (byte)((minute-(StreamID[10]-'0')*10)+'0');   
                 
              StreamID[12] = (byte)(second/10+'0');   
              StreamID[13] = (byte)((second-(StreamID[12]-'0')*10)+'0');   
                 
              StreamID[14] = (byte)(seq/10+'0');   
              StreamID[15] = (byte)((seq-(StreamID[14]-'0')*10)+'0');      
                 
              System.out.println("现在时间");   
              System.out.println("用Calendar.getInstance().getTime()方式显示时间: " + ca.getTime());   
              System.out.println("用Calendar获得日期是:" + year +"年"+ month +"月"+ day + "日");         
              System.out.println("用Calendar获得时间是:" + hour +"时"+ minute +"分"+ second +"秒");   
           
                 
        }   
           
      
        public static void main(String[] args)    
        {   
            {   
                newsDetail nn1 = new newsDetail();   
            }   
            try {   
                Thread.currentThread().sleep(3000);   
            } catch (InterruptedException e) {   
                // TODO Auto-generated catch block   
                e.printStackTrace();   
            }    
            

  • 相关阅读:
    掌控像素的虚实
    多用组合,少用继承
    HTML5的语法变化和新增加元素
    又逢六月
    设计心情之心情设计
    web2.0生成器(超过100个)[转]
    css+div CSS教程——元素定位
    项目进度
    清华大学统一认证接口与PHP的调用
    将51JOB的求职意向选择框Down了
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3159667.html
Copyright © 2011-2022 走看看