5

我用 Java 创建了一个客户端,我只想将一些数据发送到我的 C# 中的服务器。

问题是,如果我在客户端写例如你好,我只收到第一个字母。在字节数组中只有一个元素。

我猜服务器端有一些问题,因为在我的 JAVA 服务器中一切正常,所以 JAVA 中的客户端工作正常。

有人看到有什么问题吗?

先感谢您。

4

3 回答 3

3

正如 Damon Gant 所说,TCP 是一种流协议。我建议您创建自己的协议。我不会发送字符串。如果您正在做任何不平凡的事情,这确实是最好的方法。

通常我会在我的协议头中包含一个幻数、校验和、以字节为单位的数据包主体长度和协议版本。幻数可以更轻松地描述流中的数据包(对于调试自定义协议流非常有用。)拥有校验和有助于确保您正确解析事物。校验和对 TCP 的完整性没有多大帮助,因为 TCP 协议已经有校验和。数据包正文长度可帮助您检测何时拥有数据包的所有字节。协议版本可以帮助您了解如何解释数据包主体的字节。

收到数据后,将所有字节放入单独的缓冲区并扫描您的协议头。如果您可以解析您的标头,请检查该数据包的所有字节是否都存在。如果是,则解析数据包。重复这个过程,直到你找到一个不完整的数据包,或者缓冲区是空的。

对于您要发送的每个数据包,我会创建一个类。当您想发送数据包时,创建并序列化正确的类,并为该类的字节添加您的协议标头。

您可以使用 Java 的序列化程序,但如果您有多个客户端连接到单个服务器,您可能不想将 Java 用于服务器。这使事情变得困难,因为现在您需要用另一种语言实现 java 序列化程序。因此,最好手动将数据包转换为字节(繁琐但简单),或者您可以使用反射编写自己的序列化程序。我建议后者用于更大的项目。

于 2012-10-28T19:04:07.790 回答
3

您以错误的方式考虑 TCP,您不会简单地“接收”一次并获得一次“发送”的结果。

TCP 是一种“流”协议,不会自动分成“数据包”。您甚至可以在一次接收中获得 2 次发送的数据。

一种常见的模式是在一条消息前面加上它的长度,这样你就可以调用receive,直到你得到请求的字节数。如果缓冲区中没有数据,要让 Receive 立即返回,请将您的套接字设置为 non-blocking

这是关于该主题的另一篇好文章。

现在,您提供的代码应该可以以任何一种方式工作,因为本地网络上几乎没有延迟。您是否检查过您的 Java 部件是否缓冲了蒸汽/您可以手动刷新它们吗?

于 2012-10-28T18:44:11.833 回答
2

问题可能出在 java 方面,因为您的侦听器工作正常。我将您的侦听器代码复制粘贴到测试应用程序中。然后我创建了另一个测试应用程序并发送你好词,我完全听了它。

public static  void sender()
{
  TcpClient client = new TcpClient();
  IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.236"), 30000);
  client.Connect(serverEndPoint);
  NetworkStream clientStream = client.GetStream();
  ASCIIEncoding encoder = new ASCIIEncoding();
  byte[] buffer = encoder.GetBytes("Hello Server!");

  clientStream.Write(buffer, 0, buffer.Length);
  clientStream.Flush();
}


Connection accepted from 192.168.2.236:22811
Recieved...
Hello Server!

顺便说一句,这可能是更好的听众。

public void listener()
    {
  TcpListener tcpListener = new TcpListener(IPAddress.Any, 30000);
  tcpListener.Start();

  TcpClient tcpClient = tcpListener.AcceptTcpClient();
  NetworkStream clientStream = tcpClient.GetStream();

  byte[] message = new byte[4096];
  int bytesRead;

  while (true)
  {
    bytesRead = 0;

    try
    {
      //blocks until a client sends a message
      bytesRead = clientStream.Read(message, 0, 4096);
    }
    catch
    {
      //a socket error has occured
      break;
    }

    if (bytesRead == 0)
    {
      //the client has disconnected from the server
      break;
    }

    //message has successfully been received
    ASCIIEncoding encoder = new ASCIIEncoding();
    Console.Write(encoder.GetString(message, 0, bytesRead));
  }

  tcpClient.Close();
}
于 2012-10-28T18:44:18.680 回答