2012-10-28 35 views
5

我在Java中创建了一个客户机,我只是简单地将一些数据发送到我在C#中的服务器。客户机/服务器应用程序 - 丢失字节

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

我想服务器端存在一些问题,因为在我的JAVA服务器中工作得很好,所以在JAVA中的客户端工作正常。

有人看到任何问题吗?

预先感谢您。

+1

您是否调试了解k是否大于1? –

+0

K = 1.如果我搞清楚了,它应该是字节数组中有多少个元素。但由于只有一个元素,因此k = 1。 – Kubik

+0

尝试在发送数据后刷新输出流。 –

回答

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(); 
} 
+0

谢谢!这个聆听者的作品。即使我仍然不明白为什么前一个没有。 – Kubik

3

您正在考虑TCP错误的方式,您不只是简单地“接收”一次,并得到一个“发送”的结果。

TCP是一种“流式传输”协议,不会自动分成“数据包”。您甚至可以在一次收到2个发送数据。

一种常见的模式是在一条消息的前面添加长度的前缀,这样您就可以调用接收,直到获得请求的字节数。如果缓冲区中没有数据,立即使Receive返回,set your socket to non-blocking。现在

Here's another good article on the topic.

,您所提供的代码应工作无论哪种方式,因为旁边的本地网络没有延迟出现。你有没有检查你的Java部分缓冲蒸汽/你可以手动冲洗它们?

3

正如戴蒙甘特说,TCP是流协议。我建议你创建你自己的协议。我不会发送字符串。如果你做的不重要,这真的是最好的选择。

通常我会在协议头文件中包含幻数,校验和,数据包体长度以及协议版本。幻数使得在流中描绘数据包变得更加容易(对于调试自定义协议流非常有用)。校验和有助于确保正确解析事情。由于TCP协议已经具有校验和,校验和对TCP的完整性没有多大帮助。数据包体长度可帮助您检测何时获得数据包的所有字节。协议版本可以帮助您了解如何解释数据包主体的字节。

收到数据后,将所有字节放入单独的缓冲区并扫描您的协议头。如果你能解析你的头文件,那么检查一下这个数据包的字节是否全部存在。如果是这样,解析数据包。重复此过程直到找到不完整的数据包,或者缓冲区为空。

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

您可以使用Java的序列化程序,但是如果您有很多客户端连接到单个服务器,那么您可能不希望为服务器使用Java。这使事情变得困难,因为现在你需要用另一种语言来实现Java序列化程序。正因为如此,它通常更好地将数据包手动转换为字节(乏味但简单),或者您可以使用反射来编写自己的序列化程序。我建议后者更大的项目。

相关问题