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