sinboy的菜地

一份耕耘,一份收获

用户操作
[即时聊天] [发私信] [加为好友]
张新波ID:sinboy
86525次访问,排名1111好友4人,关注者27
sinboy的文章
原创 49 篇
翻译 0 篇
转载 2 篇
评论 105 篇
sinboy的公告

喜欢中文分词技术的朋友请入http://groups.google.com/group/ictclas

最近评论
lcm62975723:谢谢你。
不知是否能给出一个完整的源代码。我的email是:
lichunming3793789@126.com
leon:您好! 我也需要JAVA版的ICTCLAS源码一份
非常感谢您
我的邮箱是 leiyongekin@126.com
再次谢谢您了。
yuzishui:呵呵,都是要源码的。
谢谢您的知识.
也希望您能坚持下去.
支持.
周梁:怎么就这两句话?赶紧加强啊。
xazl.ia.ac.cn@gmail.com
周梁:我刚开始看,这里我觉得楼主可能没有理解,
作者的原意是为了防止权重相同的节点,<判断就是和=判断区别开,如果出现=,i就不会增加,继续会在这个权重下面进行插入父节点。呵呵。
可以参考他的论文一段话:

如果两条或两条以上路径长度相等,那么他们的长度并列第i,都要列入粗分结果集,而且不影响其他路径的排列序号,最后的粗分结果集合大小大于或等于N。
文章分类
收藏
    相册
    IO
    TPTP
    友情链接
    DanceFire的BLOG
    Justin的BLOG
    Martin Fowler
    博客园设计模式
    吕震宇的BLOG
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 在网络中使用IO流进行数据收发收藏

    新一篇: ICTCLAS分词系统研究(六)--得到初分结果 | 旧一篇: 单源点最短路径Dijkstra算法的JAVA实现

     
    在Java当中,所有对外设的操作都通过IO流来实现,不管是从磁盘中读取或写入文件,或者是从网络环境中接收或发送数据。IO流的基类有两个InputSstream和OutputStream,它们实现IO最基本的、无数据缓冲的、按节节流进行读写的操作功能。但是在实际的处理当中,为了数据读写的方便或提高读写的效率,往往会用到它们的子类,比如带缓冲区的类BufferedInputStream、BufferedOutputStream,DataInputStream、DataOutputStream等等。
     
    现在,我要来模拟一个常见的网络模型:客户端/服务器模式,来了解网络IO流的具体操作。首先我定义数据包的格式分别为消息头和消息体,其中消息头由三部分组成:消息包的总长度、命令字、序列号,各为一个整形,消息体为一个Byte数组,由若干字节组成,长度由消息包的总长度减去12个消息头的长度得来,消息体当中有一部分是消息内容,这个具体的组成不再详述,消息包的定义不是我们关注的重点,我们着重来看一下数据发送、接收的实现及效率如何。
     
    首先来写一个服务端的程序来接收数据,写一个客户端程序来发送数据,总共发送1万条数据进行测试,服务器端代码如下:
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;

    import com.gftech.cmpp.bean.CmppBody;
    import com.gftech.cmpp.bean.CmppDeliver;
    import com.gftech.cmpp.bean.CmppHead;
    import com.gftech.cmpp.bean.CmppPack;
    import com.gftech.cmpp.bean.ICmppCmdID;
    import com.gftech.smp.SmpDeliverPack;

    /**
     * 测试读取速度:使用Buffer和不使用Buffer的情况
     * 
     * 
    @author sinboy
     * 
    @since 2007.3.30
     * 
     
    */

    public class ServerDemo 

        
    public static void main(String[] args) {
            
    int listenPort = 2000;
            
    try {
                Socket client 
    = null;
                ServerSocket ss 
    = new ServerSocket(listenPort);
                System.out.println(
    "侦听" + listenPort + "端口,等待客户端的连接...");
                
    while (true{
                    client 
    = ss.accept();
                    System.out.println(
    "接收到通信平台或客服系统的连接" + client.toString());
                      
                    read(client);
                }

            }
     catch (IOException e) {
                e.printStackTrace();
            }

        }


        
    public static void read(Socket sock) 
            
    if (sock != null)
                
    try 
                    
    while (true{
                        CmppPack cp 
    = CmppCommu.receive(sock);
                        
    if (cp != null{
                            CmppHead head 
    = cp.getHead();
                            CmppBody body 
    = cp.getBody();
                            
    if (head != null{
                                
    switch (head.getCmdID()) {
                                
    case ICmppCmdID.CMPP_DELIVER:
                                    CmppDeliver cd 
    = new CmppDeliver(body.getBody());
                                    
    if (cd != null{
                                        SmpDeliverPack pack 
    = new SmpDeliverPack(cd);
                                        String content 
    = "cmpp deliver:" + pack.getSrcAddr() + " " + pack.getDestAddr() + " " + pack.getContent() + " "
                                                
    + pack.getLinkID();
                                        System.out.println(content);

                                    }

                                }

                            }

                        }

                    }

                }
     catch (IOException e) {
                    e.printStackTrace();
                }

        }

     
    }


        
    public void send(byte[] b) throws IOException {
            
    if (sock == null)
                
    throw new IOException();
            
    if (b != null{
                
    try {
                    BufferedOutputStream os 
    = new BufferedOutputStream(sock.getOutputStream());
                    
    if (b != null{
                        os.write(b);
                        os.flush();
                    }

                }
     catch (IOException e) {
                    
    throw e;
                }

            }

        }

     

     客户端代码如下:

    public class ClientDemo {
     
        
    public static void main(String[] args) {
            
    try 
                Socket client 
    = new Socket("192.168.10.8"2000);
                write(client);
            }
     catch (UnknownHostException e) {
                e.printStackTrace();
            }
     catch (IOException e) {
                e.printStackTrace();
            }


        }


        
    public static void write(Socket client) {
            
    try {
                ArrayList
    <CmppPack> cpList = new ArrayList<CmppPack>();
                
    for (int i = 0; i < 10000; i++{
                    SmpDeliverPack pack 
    = new SmpDeliverPack("13612345678""01234""" + (i + 1));
                    CmppDeliver cd 
    = pack.toCmppDeliver();
                    
    if (cd != null{
                        CmppPack cp 
    = new CmppPack(new CmppHead(12 + cd.getBody().length, ICmppCmdID.CMPP_DELIVER, 100), cd);
                        cpList.add(cp);
                    }

                }

              
                
    for (int i = 0; i < cpList.size(); i++{
                    CmppCommu.send(client,cpList.get(i));
                    System.out.println(i);
                }

                    Thread.sleep(
    10000);
            }
     catch (IOException e) 
                e.printStackTrace();
            }
     
            
    catch (InterruptedException e) {

            }

        }
      
    }

    用到的发送和接入方法如下:

    public class CmppCommu {

        
    public static void send(Socket sock, CmppPack pack) throws IOException {
            
    if (sock != null && pack != null{
                
    try {
                    
    byte[] b = pack.getBytes();
                    BufferedOutputStream os 
    = new BufferedOutputStream(sock.getOutputStream());
                    
    if (b != null{
                        os.write(b);
                        os.flush();
                    }

                }
     catch (IOException e) {
                    
    throw e;
                }

            }


        }

    public static CmppPack receive(Socket sock) throws IOException {
            
    final int MAX_LEN = 10000;
            CmppPack pack 
    = null;

            
    if (sock == null)
                
    throw new IOException();
            
    try {
                BufferedInputStream bis 
    = new BufferedInputStream(sock.getInputStream());
                DataInputStream in 
    = new DataInputStream(bis);

                
    int len = in.readInt();// 读取消息头
                if (len >= 12 && len < MAX_LEN) {
                    
    int cmd = in.readInt();
                    
    int seq = in.readInt();

                    
    int bodyLen = len - 12;
                    
    byte[] msg = new byte[bodyLen];
                    in.read(msg);
    // 读取消息体

                    CmppHead head 
    = new CmppHead(len, cmd, seq);
                    CmppBody body 
    = new CmppBody(msg);
                    pack 
    = new CmppPack(head, body);
                }

            }
     catch (SocketTimeoutException e) {
                
    // logger.warn("time out");
            }
     catch (IOException e) {
                
    throw e;
            }


            
    return pack;
        }

    }

    使用Eclipse TPTP对程序的执行进行监控,结果如下:

     

    如上图所示,服务器端程序在接收数据时总共花了21秒多。因为从理论上讲把输入流用Buffer包装一下接收的速度会更快一些,下面我们对它进行验证,把接收程序略做改动,增加一句Buffer包装: 

    BufferedInputStream bis = new BufferedInputStream(sock.getInputStream());
    DataInputStream in 
    = new DataInputStream(bis);

    再次运行,发现一个很奇怪的问题,接收时有数据丢失的情况,正常情况下应该是从110000

    cmpp deliver:13612345678 01234 1 16240905710000010001
    cmpp deliver:
    13612345678 01234 2 16241005710000010001
    cmpp deliver:
    13612345678 01234 261 16241005710000010001
    cmpp deliver:
    13612345678 01234 262 16241005710000010001
    cmpp deliver:
    13612345678 01234 263 16241005710000010001
    cmpp deliver:
    13612345678 01234 264 16241005710000010001
    . . . . . .

     

    为何用Buffer进行包装之后会有数据丢失而没有包装时接收正常呢?我们仔细研究一下接收的源代码发现,在每次对数据进行接收时,都会在一个Socket上重新建一个输入流,因为BufferedInputStream在创建时会自动建立一个缓冲区用于整块数据的读取,系统默认为8192,也就是说当你读第一个包的时候,系统本身其实已经读取的8192个字节的数据,而你的包大小可能是只有100个字节,在你循环过来再次读第二个数据包时,等于又重新创建了一个输入流,把前面那个丢掉了,而它原先已经预先读取的数据也随之丢失。而不用Buffer包装的输入流因为每次都是从实际的IO中读取数据所以不存在数据丢失的情况。

    明白了这一点,那我们可以把创建输入流放到每次读取的循环之外,修改读取方法如下:

    public static CmppPack receive(DataInputStream in) throws IOException {
            
    final int MAX_LEN = 10000;
            CmppPack pack 
    = null;
            
    if (in == null)
                
    throw new IOException();
            
    try {
                
    int len = in.readInt();// 读取消息头
                if (len >= 12 && len < MAX_LEN)