【问题标题】:Client for a local Java based service本地基于 Java 的服务的客户端
【发布时间】:2013-03-01 21:28:09
【问题描述】:

我正在尝试将我的 C# 应用程序与基于 Java 的本地服务连接起来。我无法访问 Java 代码和服务详细信息,我唯一知道的是通过指定端口通过套接字进行通信。

问题是我可以连接但无法发送/接收任何数据。我的 C# 客户端代码如下;

======================

IPHostEntry ipAddress = Dns.GetHostEntry("127.0.0.1");
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(ipAddress.AddressList[0].ToString()), 8888);
socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(ip);

Encoding ASCII = Encoding.ASCII;
Byte[] byteGetString = ASCII.GetBytes("Service_Command_Message");
Byte[] receivedBytes = new Byte[256];
string l_Response = string.Empty;

socket.Send(byteGetString, byteGetString.Length, SocketFlags.None);

//debugger gets lost at this line. I also tried stream.read    
Int32 bytes = socket.Receive(receivedBytes, receivedBytes.Length, SocketFlags.None);
l_Response += ASCII.GetString(receivedBytes, 0, bytes);
while (bytes > 0)
{
    bytes = socket.Receive(receivedBytes, receivedBytes.Length, SocketFlags.None);
    l_Response = l_Response + ASCII.GetString(receivedBytes, 0, bytes);
}
socket.Close();

======================

我尝试使用一些端口捕获工具,该工具显示连接性,但传输数据的长度显示为 0。

感谢您的帮助。

=======更新(使用TcpClinet发送)==========

client = new TcpClient("127.0.0.1", 8888);
stream = client.GetStream();

Byte[] data = System.Text.Encoding.ASCII.GetBytes("Service_Command_Message");

StreamWriter sw = new StreamWriter(stream);

sw.WriteLine(p_Message);
sw.Flush();

=========================================

我使用了 Flush(),但在我关闭应用程序之前仍然没有传输数据。

【问题讨论】:

  • 首先,使用 SocketFlags 枚举值来提高发送/接收方法的可读性。其次,您能否从发送/接收的输出参数中获取错误代码,第三,无论如何验证字节是否正在 java 端发送/接收? (我假设没有这个)
  • 就 read(..)/receive(..) 而言,我无法得到它的输出参数,因为应用程序/调试器在此语句处挂起。我无法检查在 Java 端收到了什么,我没有它的代码,它作为带有一些 .jar(s) 和 .class(es) 的可执行文件提供。但是,我已经提到传输的数据在本地循环嗅探器工具上显示为 0 长度。
  • 只要我的 C# 应用程序正在运行,传输的数据就是 0,当我关闭它时,它会将数据“刷新”到接收器,然后数据显示在数据包捕获工具和 Java 中服务器的日志。如何刷新套接字缓冲区?或者我需要在消息末尾添加一个空/终止字符?我也尝试过使用 TcpClient,请查看 TcpClient 代码。它也有即使在使用 Flush() 后也会出现同样的问题。

标签: c# java sockets client tcpclient


【解决方案1】:

由于您的代码命中了接收方法,我假设发送方法没有任何问题。您应该查看SocketError 的输出参数来验证这一点。

首先,您不能依赖套接字发送或接收所有数据。您发送的字节数总是有可能超出客户的预期。 Socket.Send 方法返回发送的字节数,因此您可以使用它来确定您是否已发送所有字节:

Byte[] byteGetString = ASCII.GetBytes("Service_Command_Message");
int count = 0;
while (count < byteGetString.Length ) 
{
    count += socket.Send(
        bytes,
        count, 
        bytes.Length - count, 
        SocketFlags.None)
}

你的接收方法挂起的原因可能是因为你的while循环条件:

while (bytes > 0) {
    bytes = socket.Receive(receivedBytes, receivedBytes.Length, SocketFlags.None);
    l_Response = l_Response + ASCII.GetString(receivedBytes, 0, bytes); }

您假设当您收到零长度字节时,您已完成接收,但情况可能并非如此。当您在最后一个循环的缓冲区中填充一些字节时,您可能已经到达网络流的末尾。因此,您必须像这样更改 while 循环条件:

while (bytes == receivedBytes.Length) {
    bytes = socket.Receive(receivedBytes, receivedBytes.Length, SocketFlags.None);
    l_Response = l_Response + ASCII.GetString(receivedBytes, 0, bytes); }

如果这一切都失败了,很可能是服务器没有正确发送/接收字节。

最后,请务必处理SocketException,因为随时可能断开连接。

【讨论】:

  • 我从 Java Server 的日志中注意到,在我退出挂起的应用程序后收到了我的数据。这是否意味着退出前自动刷新?我自己怎么能做到这一点?也许未刷新的“发送”阻止了“接收”。
猜你喜欢
  • 1970-01-01
  • 2010-10-08
  • 2017-11-27
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 2016-05-26
  • 2012-01-10
  • 1970-01-01
相关资源
最近更新 更多