Socket通信的一个奇怪现象,大家一起来看看

通信模型:



1.客户端发送76字节的封包

2.服务器收到76字节封包、返回2133字节封包到客户端

3.客户端收到2133字节封包、返回16字节封包做响应

4.客户端发送76字节封包

5.服务器端收到16字节封包,不做处理

6.回到2的操作



运行环境:

Java1.5

局域网(本机测试不会发生下面的问题)



现象:

1.使用上面的通信模型,客户端两次发出76字节封包的间隔需要40ms之久(依网络情况而定)

2.如果将将第3步的后半部分去掉,即客户端不发送16字节响应,客户端两次发送76字节封包的间隔变成只有0-1ms

3.如果第3步不变,使服务器端收到16字节封包后随便给客户端回应个什么,那么客户端两次发送76字节封包的间隔也变成了0-1ms



总之,如果客户端与服务器端的封包是一一对应的话,速度将很快。如果客户端发3个包,服务端响应一次的话,速度将非常慢。



不知道是JAVA本身的问题,还是TCP的机制本就如此?



下面是服务器端和客户端代码:



Client.java

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Client {

/**
 * @param args
 */
public static void main(String[] args) throws Exception{

    Socket socket = new Socket();
    System.out.println("Connecting...");
    socket.connect(new InetSocketAddress(InetAddress.getByName("10.2.2.141"),9999));

    System.out.println("Connected.");

    InputStream in = socket.getInputStream();
    OutputStream out = socket.getOutputStream();

    out.write(new byte[76]);
    out.flush();

    int i = 0;
    long t = System.currentTimeMillis();

    byte[] delivery = new byte[2133];

    while(in.read(delivery) != -1){

        // 16字节响应,如果不发送响应,通信速度将大幅提升
        out.write(new byte[16]);
        out.flush();

        out.write(new byte[76]);

        out.flush();

        if(++i % 100 == 0){//计算两次发送76字节封包间的平均时间
            System.out.println("TIME: " + (System.currentTimeMillis() - t) / 100);
            t = System.currentTimeMillis();
        }


    }

}

}





TServer.java

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TServer {

public static void main(String[] args) throws Exception{
    ServerSocket ss = new ServerSocket();

    System.out.println("Server starting...");
    ss.bind(new InetSocketAddress(InetAddress.getByName("10.2.2.141"), 9999));

    Socket socket = ss.accept();
    System.out.println("Client connected: " + socket.getRemoteSocketAddress());

    InputStream in = socket.getInputStream();
    OutputStream out = socket.getOutputStream();

    int r = 0;
    byte[] b = new byte[2048];
    while((r = in.read(b)) != -1){
        if(r == 76){
            System.out.println("GET");
            out.write(new byte[2133]);
            System.out.println("DELIVERY");
        }else if(r == 16){
            System.out.println("RESP");
            //如果收到16字节封包后随便回应点东西给客户端,速度也将大幅提升
            //out.write(new byte[2133]);
        }
    }
}

}



1个回答

set tcpNoDelay=true in socket opt both server and client side.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐