我在Java中创建了一个客户机,我只是简单地将一些数据发送到我在C#中的服务器。客户机/服务器应用程序 - 丢失字节
问题是,如果我在客户端写入例如你好,我只得到第一个字母。在字节数组中只有一个元素。
我想服务器端存在一些问题,因为在我的JAVA服务器中工作得很好,所以在JAVA中的客户端工作正常。
有人看到任何问题吗?
预先感谢您。
我在Java中创建了一个客户机,我只是简单地将一些数据发送到我在C#中的服务器。客户机/服务器应用程序 - 丢失字节
问题是,如果我在客户端写入例如你好,我只得到第一个字母。在字节数组中只有一个元素。
我想服务器端存在一些问题,因为在我的JAVA服务器中工作得很好,所以在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();
}
谢谢!这个聆听者的作品。即使我仍然不明白为什么前一个没有。 – Kubik
您正在考虑TCP错误的方式,您不只是简单地“接收”一次,并得到一个“发送”的结果。
TCP是一种“流式传输”协议,不会自动分成“数据包”。您甚至可以在一次收到2个发送数据。
一种常见的模式是在一条消息的前面添加长度的前缀,这样您就可以调用接收,直到获得请求的字节数。如果缓冲区中没有数据,立即使Receive返回,set your socket to non-blocking。现在
Here's another good article on the topic.
,您所提供的代码应工作无论哪种方式,因为旁边的本地网络没有延迟出现。你有没有检查你的Java部分缓冲蒸汽/你可以手动冲洗它们?
正如戴蒙甘特说,TCP是流协议。我建议你创建你自己的协议。我不会发送字符串。如果你做的不重要,这真的是最好的选择。
通常我会在协议头文件中包含幻数,校验和,数据包体长度以及协议版本。幻数使得在流中描绘数据包变得更加容易(对于调试自定义协议流非常有用)。校验和有助于确保正确解析事情。由于TCP协议已经具有校验和,校验和对TCP的完整性没有多大帮助。数据包体长度可帮助您检测何时获得数据包的所有字节。协议版本可以帮助您了解如何解释数据包主体的字节。
收到数据后,将所有字节放入单独的缓冲区并扫描您的协议头。如果你能解析你的头文件,那么检查一下这个数据包的字节是否全部存在。如果是这样,解析数据包。重复此过程直到找到不完整的数据包,或者缓冲区为空。
对于每个要发送的数据包,我都会创建一个类。当你想发送一个数据包时,创建并序列化正确的类,并为该类的字节添加协议头。
您可以使用Java的序列化程序,但是如果您有很多客户端连接到单个服务器,那么您可能不希望为服务器使用Java。这使事情变得困难,因为现在你需要用另一种语言来实现Java序列化程序。正因为如此,它通常更好地将数据包手动转换为字节(乏味但简单),或者您可以使用反射来编写自己的序列化程序。我建议后者更大的项目。
您是否调试了解k是否大于1? –
K = 1.如果我搞清楚了,它应该是字节数组中有多少个元素。但由于只有一个元素,因此k = 1。 – Kubik
尝试在发送数据后刷新输出流。 –