【问题标题】:java tcp messaging not working but .net version doesjava tcp 消息传递不起作用,但 .net 版本可以
【发布时间】:2016-08-12 11:29:20
【问题描述】:

我正在尝试使用 tcp 套接字连接将 json 消息发送到特定的 ip 和端口。该代码似乎适用于初始连接和消息提交,但在检查目标服务器时,我没有找到消息。我有一个也可以运行的 .NET 版本,出于某种原因,尝试发送完全相同的消息可以正常工作。我尝试使用wireshark捕获数据包和连接,但似乎根本没有设置任何数据包。

wireshark 捕获:

java中的代码:

  try

    {



        clientSocket = new Socket(ipaddress, portnumber);
        outStreamSplunk = new PrintWriter(clientSocket.getOutputStream(), true);
        outStreamSplunk.flush();
        clientSocket.setKeepAlive(true);
        clientSocket.setSoTimeout(1000);


        outStreamSplunk.println(post + "\n");
        System.out.println("SENT MESSAGE: " + post);
        clientSocket.close();

    }
    catch (Exception exc)
    {
         modifiedSentence = "";
    }

以及 .NET 中有效的代码:

    ip = "xxx.xxx.x.xxx"
    port = xxxx


    Dim ips As String = Dns.GetHostEntry(ip).AddressList(0).ToString()
    _GLOIP = IPAddress.Parse(ips)
    _port = port

    'initiate the client and get the stream to use
    myTcp = initiate()
    netStream = myTcp.GetStream() 

Try

        If netStream.CanWrite Then
            If Not text.EndsWith(vbCr & vbLf) Then
                text += Environment.NewLine
            End If

            Dim sendBytes As Byte() = Encoding.UTF8.GetBytes(text)
            netStream.Write(sendBytes, 0, sendBytes.Length)

        Else
            err = "cannot write to the stream"
        End If

    Catch ex As Exception
        appLogs.constructLog(err & vbNewLine & ex.Message.ToString, True, True)
        Exit Sub
    End Try

编辑:

我尝试了另一台服务器,因为我认为它可能是我的机器,并且 .NET 脚本在另一台机器上运行。结果表明 TCP 连接工作正常,但不知道如何解释响应:

我没有看到任何错误,因此可能是目标服务器的问题。 .NET 版本和 java 版本之间的唯一区别是 .NET 版本正在写入字节数组。这让我很难过。但是如果我没有找到解决方案,我将需要用 .NET 版本并以某种方式将消息从主 java 代码传输到 .NET 版本。

【问题讨论】:

  • 这不是一个好的异常处理程序...
  • 不同之处在于异常处理程序......在.Net版本中,您正在记录错误。在 Java 版本中,您将忽略它。至少添加一个exc.printStackTrace()
  • 此外,.Net 代码首先不包括建立连接。由于您在 Java 版本中没有看到任何数据包通过网络传输,因此您的问题似乎就出在这上面。猜测一下,ipaddressportnumber 是无效的,因此甚至没有尝试连接(因为 Wireshark 会看到连接尝试)。
  • 谢谢大家。将首先更改异常处理程序并尝试。
  • 没有发现异常。代码中似乎没有任何错误。我可以从命令提示符 ping ip,然后尝试进行 telnet 连接,但失败了:无法在端口上打开与主机的连接,连接失败。如果我在这里混淆了网络协议但只是想尝试一切,请原谅我

标签: java sockets tcp


【解决方案1】:

您的 Java 代码不等同于您的 VB.NET 代码。


Java

您使用PrintWriter 并不能保证 UTF-8 编码:

public void println(String x)

打印String,然后终止该行。 此方法的行为就像调用print(String),然后调用println()

public void print(String s)

打印一个字符串。如果参数是null,则打印字符串“null”。否则字符串的字符按照平台默认的字符编码转换为字节,这些字节完全按照write(int)方法的方式写入。

因此,不能保证您会发送 UTF-8。相反,请使用 OutputStreamWriter 并为其分配 UTF-8 Charset

另外,您要发送 2 个行终止符,一个在 string 数据中显式,另一个在 println() 中隐式发送。

试试这个:

try
{
    clientSocket = new Socket(ipaddress, portnumber);
    clientSocket.setKeepAlive(true);
    clientSocket.setSoTimeout(1000);

    outStreamSplunk = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8));
    outStreamSplunk.write(post);
    if (!post.endsWith("\r\n"))
        outStreamSplunk.write("\r\n");
    outStreamSplunk.flush();

    System.out.println("SENT MESSAGE: " + post);

    clientSocket.close();
}
catch (Exception exc)
{
    // log exc.toString() as needed....
    return;
}

VB.NET

代码强制使用 UTF-8,并且只发送一个行终止符。但是,Environment.NewLine 是特定于平台的,不能保证是CRLF,因此请改用vbCrLf

另外,使用IPAddress.Parse() 解析AddressList(0).ToString() 的结果是多余的开销,因为AddressList(0) 返回一个IPAddress 开头,所以直接使用它。

此外,如果 Dns.GetHostEntry()initialize() 失败,您不会捕获异常来记录它。

试试这个:

'ip = "xxx.xxx.x.xxx"
'port = xxxx

Try
    _GLOIP = Dns.GetHostEntry(ip).AddressList(0)
    _port = port

    'initiate the client and get the stream to use
    myTcp = New TcpClient(New IPEndPoint(_GLOIP, _port))
    netStream = myTcp.GetStream() 

    Dim bufStream As BufferedStream = New BufferedStream(netStream)

    Dim sendBytes As Byte() = Encoding.UTF8.GetBytes(text)
    bufStream.Write(sendBytes, 0, sendBytes.Length)

    If Not text.EndsWith(vbCrLf) Then
        sendBytes = Encoding.UTF8.GetBytes(vbCrLf)
        bufStream.Write(sendBytes, 0, sendBytes.Length)
    End If

    bufStream.Flush()

Catch ex As Exception
    appLogs.constructLog(err & vbNewLine & ex.Message.ToString, True, True)
    Exit Sub
End Try

或者,您可以使用接受字符串作为输入的TcpClient 构造函数,并且根本不调用Dns.GetHostEntry()

'ip = "xxx.xxx.x.xxx"
'port = xxxx

_GLOIP = ip
_port = port

...

'initiate the client and get the stream to use
myTcp = New TcpClient(_GLOIP, _port)

【讨论】:

    【解决方案2】:

    你的同花顺放错了地方。它应该在写入之后,而不是在它之前,这完全没有意义。实际上,您应该只关闭编写器而不是套接字:这将刷新编写器并关闭套接字。目前,数据永远不会从写入器中流出到套接字中。

    【讨论】:

      猜你喜欢
      • 2010-10-20
      • 1970-01-01
      • 2016-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多