我用 Java 创建了一个客户端,我只想将一些数据发送到我的 C# 中的服务器。
问题是,如果我在客户端写例如你好,我只收到第一个字母。在字节数组中只有一个元素。
我猜服务器端有一些问题,因为在我的 JAVA 服务器中一切正常,所以 JAVA 中的客户端工作正常。
有人看到有什么问题吗?
先感谢您。
正如 Damon Gant 所说,TCP 是一种流协议。我建议您创建自己的协议。我不会发送字符串。如果您正在做任何不平凡的事情,这确实是最好的方法。
通常我会在我的协议头中包含一个幻数、校验和、以字节为单位的数据包主体长度和协议版本。幻数可以更轻松地描述流中的数据包(对于调试自定义协议流非常有用。)拥有校验和有助于确保您正确解析事物。校验和对 TCP 的完整性没有多大帮助,因为 TCP 协议已经有校验和。数据包正文长度可帮助您检测何时拥有数据包的所有字节。协议版本可以帮助您了解如何解释数据包主体的字节。
收到数据后,将所有字节放入单独的缓冲区并扫描您的协议头。如果您可以解析您的标头,请检查该数据包的所有字节是否都存在。如果是,则解析数据包。重复这个过程,直到你找到一个不完整的数据包,或者缓冲区是空的。
对于您要发送的每个数据包,我会创建一个类。当您想发送数据包时,创建并序列化正确的类,并为该类的字节添加您的协议标头。
您可以使用 Java 的序列化程序,但如果您有多个客户端连接到单个服务器,您可能不想将 Java 用于服务器。这使事情变得困难,因为现在您需要用另一种语言实现 java 序列化程序。因此,最好手动将数据包转换为字节(繁琐但简单),或者您可以使用反射编写自己的序列化程序。我建议后者用于更大的项目。
您以错误的方式考虑 TCP,您不会简单地“接收”一次并获得一次“发送”的结果。
TCP 是一种“流”协议,不会自动分成“数据包”。您甚至可以在一次接收中获得 2 次发送的数据。
一种常见的模式是在一条消息前面加上它的长度,这样你就可以调用receive,直到你得到请求的字节数。如果缓冲区中没有数据,要让 Receive 立即返回,请将您的套接字设置为 non-blocking。
现在,您提供的代码应该可以以任何一种方式工作,因为本地网络上几乎没有延迟。您是否检查过您的 Java 部件是否缓冲了蒸汽/您可以手动刷新它们吗?
问题可能出在 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();
}