V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
likefly
V2EX  ›  程序员

Java Socket 客户端读出问题了

  •  
  •   likefly · 2020-04-24 16:29:10 +08:00 · 1372 次点击
    这是一个创建于 1660 天前的主题,其中的信息可能已经有所发展或是发生改变。
    // 往服务端写
    write(param);
    
    TimeUnit.SECONDS.sleep(1);
    
    // 读取服务端返回的数据
    String data = read(param);
    

    如果中间的休眠去掉,有很大几率直接读取返回的数据会出现数据丢失,有可能只读了一半。


    read 方法代码大概是这样

    InputStream is
    // 先读八个字节
    byte[] header= new byte[8];
    is.read(header);
    
    // 转换成字符串之后再转换成整数
    int length = Integer.valueOf(new String(header));
    // 读取正文
    byte[] content = new byte[length];
    is.read(content);
    
    5 条回复    2020-04-25 13:58:47 +08:00
    twoconk
        1
    twoconk  
       2020-04-24 17:52:00 +08:00
    是有点诡异,通常网络请求是一个阻塞的,如果不是异步 IO,通常是在单独的线程中循环读,类似下面的代码:


    byte[] buffer= new byte[1024*10];
    while(1){
    int len=is.read(buffer);
    //业务在这里实现

    TimeUnit.SECONDS.sleep(1);
    }
    23571113
        2
    23571113  
       2020-04-24 18:59:24 +08:00 via Android
    用粘包警察的话来说就是粘包了
    opengps
        3
    opengps  
       2020-04-24 19:04:47 +08:00 via Android
    通常都是粘包问题,不前后拼接拿不到完整的。
    解决方案,要么处理粘包,要么设计成带回复的通信协议,不回复主动重发
    djoiwhud
        4
    djoiwhud  
       2020-04-24 19:48:51 +08:00 via Android
    第一,代码要给全,不想泄露业务就自己弄个福利的测试用例。
    第二,应该所有语言的 tcp 协议的 read 都会返回读取的实际长度。你这里压根没处理。
    第三,你应该用 nio,streambuffer 这类处理,不是 java 开发,仅仅写过 java 适配的网络模块。可能有不对的地方。
    第四,网络本身并不是阻塞的。不同语言,处理方式有差异。有些语言可以设置读超时,超时后继续下一个读轮训。
    qumingkunnan
        5
    qumingkunnan  
       2020-04-25 13:58:47 +08:00 via Android
    tcp 一直读,读到什么时候算结束应该由你的协议来定
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2591 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 05:01 · PVG 13:01 · LAX 21:01 · JFK 00:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.