本帖最后由 CCDDzclxy 于 2013-11-01 11:02:04 编辑

解决方案 »

  1.   

    在客户端这边不太好判断是否发送成功
    要知道是否发送完成,最好的办法是服务器端响应一个状态给你。
    PrintStream output = new PrintStream(skt.getOutputStream());
    output.write(bytes, 0, iLen);
    output.flush();
    //下面的代码如果继续执行表示数据已发送,至于服务器是否收到就很难说了。
      

  2.   

    这样还有TCP的优势么??这样弄还不如直接用UDP,自己弄个简单的重传机制了.......
      

  3.   

    TCP数据传输理论上 数据比UDP可靠。
    客户端都是这样处理的,需要服务器响应状态。
      

  4.   

    所谓可靠不就是重传机制么。TCP里面本来就有接收方接收到数据会回传ACK,如果发送方一段时间没收到对方的ACK就会重传,这本就是TCP里面自带的。“最好的办法是服务器端响应一个状态给你”,这样不是浪费了ACK?不是浪费流量吗???
      

  5.   

    你说的那个是TCP 底层的会保证数据完整性。正常情况下不会丢失数据。
    如果网络不稳定超时异常那就需要自己处理了。
      

  6.   

    比如我分别连续发了30次字符串“hello1”、“hello2”、“hello3”...“hello30”,但是对方网络断了。重传时间2分钟,然后抛出异常,那我如何知道 我是在 hello? 时 对方断网的?哪些字符串发送成功了,哪些没发送成功???
      

  7.   

    PrintStream output = new PrintStream(skt.getOutputStream());
    output.write("hello".getBytes(), 0, iLen); 
    output.flush();
    //如果发送这个hello后,客户没有发生异常,可以理解为这个字符串已经发送成功了,不太可能只发送了前2个字符,后面几个字符没发送,如果真没发送那就是丢包了,这种情况是罕见的。try {
      PrintStream output = new PrintStream(skt.getOutputStream());
      output.write(bytes, 0, iLen); 
      output.flush();
    }catch(Exception ex){
       //如果异常就需要处理那个字符串是没有发送成功。
    }
      

  8.   

    我的 客户端程序 基本设计成这样:
    接收数据的线程:    Runnable threadRecv = new Runnable()
        {
    @Override
    public void run()
    {
    try
    {
    byte[] byteRecv = new byte[RECV_BUF_LENGTH];

    InputStream input = Fskt.getInputStream();

    while (true)
    {
    int iRecvLen = input.read(byteRecv, 0, RECV_BUF_LENGTH ); if ((iRecvLen == 0) || (-1 == iRecvLen))
    {
    zcHandler.obtainMessage(THREAD_SKT_DEST_DISCONNECT).sendToTarget();

    final String strBreak = 
    "Socket closed by remote . Maybe connection timeout . ==> ("+Integer.toString(iRecvLen)+")";
    zcHandler.obtainMessage(THREAD_MSG, strBreak).sendToTarget();

    break; // 退出循环
    }

    ...... ......
    } // while
    }
    catch(Exception ex)
    {
    final String strErr = "Recv msg err : "+ex.getMessage()+"\r\n";
    zcHandler.obtainMessage(THREAD_MSG, strErr).sendToTarget();
    zcHandler.obtainMessage(THREAD_OVER).sendToTarget();
    }
    }
        };
    发送数据的代码:        Button btnTcpSend = (Button)findViewById(R.id.btnTcpSend);
            btnTcpSend.setOnClickListener(new Button.OnClickListener()
            {
    @Override
    public void onClick(View v)
    {
    try
    {
    FiIdx ++;
    PrintStream output = new PrintStream(Fskt.getOutputStream());
    output.write(FiIdx);
    output.flush();
    }
    catch(Exception e)
    {
    String strErr = e.getMessage();
    zcMsg_Add("Seng msg err : "+strErr);
    }
    }
            }); // btnTcpSend
    FiIdx 是初始化为 0 的类成员变量。测试步骤:
    CLient机子 和 Server机子 处于同一局域网,都是 XP 。Client机子 上运行 Android虚拟机来跑 客户端程序。
    1、Client 连上 Server 。
    2、连点 两次 btnTcpSend ,数字1、2 发出去了,server 也收到了。
    3、此时立即 禁用 Server 网卡,再立即点击 btnTcpSend 3次 。(此时时间为 12:52:15)
    4、抓包可见 ,数字3、4、5 在重传。
    5、时间 12:54:03 ,Android Client程序显示信息“Socket closed by remote . Maybe connection timeout . ==> (-1)” 。说明此时Client才知道对方断线了。(这个显示的信息是我在 接收线程里面的信息)
    这里,我是故意手动断开 server 的网络,所以我知道是 数字3、4、5 没发送成功。那么放到实际应用中,我怎么知道哪些发送成功了,哪些没发送成功 ??
    ps : 知道现在Client也没有别的信息显示
      

  9.   

    birdsaction  及 各位同仁,不管高手不高手,都来指点下啊~~~
      

  10.   

    当你拔掉网线这个从socket角度来讲 很难判断,网都断了 Socket只是个接口无法知道物理层的详细东西。以前做应用一般都是捕获异常,或者服务器返回状态,如果没收到服务器的状态吗 就继续让程序发送请求。