TCP-IP, c#客户端和Java服务器,非常高的延迟
本文关键字:非常 延迟 服务器 Java 客户端 TCP-IP | 更新日期: 2023-09-27 18:06:30
在一些基于教程的代码中,我通过web服务中的web应用程序的WebMethod
将c# web应用程序连接到Java套接字服务器。不幸的是,这一进程非常缓慢。例如,当Java服务器向c#客户端回显一些数据时,我得到以下结果:
- 发送的数据大小= 32MB,总时间= 980 ms(没有问题)
- 发送的数据大小= 4MB,总时间= 530 ms(变得有些慢)
- 发送的数据大小= 1MB,总时间= 520 ms(绝对瓶颈)
- 发送的数据大小= 1kB,总时间= 516 ms(这一定是某些恒定的延迟)
我读到人们可以进行实时通信(~60/s),有时甚至数百万流/s与一些服务器应用程序。我的实现会出现什么问题?它通过一个打开的连接发送多个消息,所以对象创建开销应该只显示第一个消息?为什么我在消息传递上有500毫秒的开销?
c# webmethod在web应用程序启动并每次调用该webmethod时连接到相同的Java服务器时启动。
public static IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
public static IPAddress ipAddress = ipHostInfo.AddressList[0];
public static IPEndPoint remoteEP = new IPEndPoint(ipAddress, 9999);
// Create a TCP/IP socket.
public static Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public static int z = 0;
[WebMethod]
public BenchmarkData_ StartClient()
{
lock(lck)
{
z++;
if (z == 1)
{
sender.Connect(remoteEP);
}
}
int bytesRec = 0;
int boy = 0;
byte[] bytes = new byte[1024 * 1024];
int bytesSent = 0;
SocketFlags sf = new SocketFlags();
Stopwatch sw = new Stopwatch(); Stopwatch sw2 = new Stopwatch();
#region r
lock (lck)
{
sw.Start();
// Data buffer for incoming data.
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// This example uses port 11000 on the local computer.
// Create a TCP/IP socket.
sender.ReceiveBufferSize = 1024 * 1024;
sender.ReceiveTimeout = 1;
// Connect the socket to the remote endpoint. Catch any errors.
try
{
Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes("This is a test<EOF>");
// Send the data through the socket.
bytesSent = sender.Send(msg);
// Receive the response from the remote device.
sw.Stop();
sw2.Start();
while ((bytesRec = sender.Receive(bytes)) > 0)
{
boy += bytesRec;
}
Console.WriteLine("Echoed test = {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
// Release the socket.
// sender.Shutdown(SocketShutdown.Both);
// sender.Close();
sw2.Stop();
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
#endregion
return new BenchmarkData_() { .... };
}
下面是Java代码(半伪代码)
serverSocket=new ServerSocket(port); // in listener thread
Socket socket=serverSocket.accept(); // in listener thread
// in a dedicated thread per connection made:
out=new BufferedOutputStream( socket.getOutputStream());
in=new DataInputStream(socket.getInputStream());
boolean reading=true;
ArrayList<Byte> incoming=new ArrayList<Byte>();
while (in.available() == 0)
{
Thread.sleep(3);
}
while (in.available() > 0)
{
int bayt=-2;
try {
bayt=in.read();
} catch (IOException e) { e.printStackTrace(); }
if (bayt == -1)
{
reading = false;
}
else
{
incoming.add((byte) bayt);
}
}
byte [] incomingBuf=new byte[incoming.size()];
for(int i = 0; i < incomingBuf.length; i++)
{
incomingBuf[i] = incoming.get(i);
}
msg = new String(incomingBuf, StandardCharsets.UTF_8);
if (msg.length() < 8192)
System.out.println("Socket Thread: "+msg);
else
System.out.println("Socket Thread: long msg.");
OutputStreamWriter outW = new OutputStreamWriter(out);
System.out.println(socket.getReceiveBufferSize());
outW.write(testStr.toString()); // 32MB, 4MB, ... 1kB versions
outW.flush();
问题解决,更换
while ((bytesRec = sender.Receive(bytes))>0)
{
boy += bytesRec;
}
while (sender.Available <= 0) ;
while (sender.Available>0)
{
bytesRec = sender.Receive(bytes);
boy += bytesRec;
}
现在以微秒为单位读取1kB,而不是500ms。因为它检查单个整数,而不是尝试读取整个缓冲区?也许吧。但是它现在不能读取从服务器发送的所有消息。它需要某种类型的标题来知道要读多少。即使服务器发送兆字节,也读取几千字节。
当服务器发送3MB并且客户端读取完全相同的量时,需要30ms。都在同一台机器上。试图读取超过服务器已发送的数据(即使是一个字节),会引发异常,因此TCP确实发送了与客户端所需的相同数量的数据。