草庐IT

java - C# 和 Java 服务器之间的 TCP 通信

coder 2023-09-18 原文

我正在尝试使用 TCP 将 json 从 C# 服务器传递到 Java 服务器,问题是 Java 服务器第一次似乎收到一个空的 json。第二次及以后它工作正常,请参阅下面的输出。欢迎任何想法或建议,在此先感谢。

输出:

Starting server...
Waiting for a connection..
Connected!
Reading...
Received empty object
Received: 
Connected!
Reading...
Received: "Request:gethotellist"
Connected!
Reading...
Received: "Request:gethotellist"

这里是发送json的C#代码片段:

public void GetHotelList()
{
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 6767);

NetworkStream ns = clientSocket.GetStream();

string jsonRequest = "Request:gethotellist";

string jsonToSend = JsonConvert.SerializeObject(jsonRequest);

byte[] dataBytes = Encoding.UTF8.GetBytes(jsonToSend);

ns.Write(dataBytes, 0, dataBytes.Length);

ns.Close();
}

Java 服务器:

public class JHotelServer
{

public static void main(String[] args) throws IOException
{
  final int PORT = 6767;

  System.out.println("Starting server...");     

  @SuppressWarnings("resource")
  ServerSocket welcomeSocket = new ServerSocket(PORT);  

  System.out.println("Waiting for a connection..");

  while(true)
  {             
     try
     {
        Socket connectionSocket = welcomeSocket.accept();  

        System.out.println("Connected!");

        Thread connectionThread = new Thread(new TcpConnectionManager(connectionSocket));
        connectionThread.start();
     }

     catch(IOException ioe)
     {
        ioe.printStackTrace();
     }         
  }
}
}

这是 Tcp 通信管理器:

public class TcpConnectionManager implements Runnable
{   
private DataInputStream inFromDotNet;

public TcpConnectionManager(Socket socket) throws IOException
{
  inFromDotNet = new DataInputStream(socket.getInputStream());
}

@Override
public void run()
{
  try
  {               
     System.out.println("Reading...");

     byte[] rvdMsgByte = new byte[inFromDotNet.available()];

     // Collecting data into byte array
     for (int i = 0; i < rvdMsgByte.length; i++)
     {
         rvdMsgByte[i] = inFromDotNet.readByte();
     }

     if (rvdMsgByte.length == 0)
     {
        System.out.println("Received empty object");
     }

     // Converting collected data in byte array into String.
     String rvdMsgTxt = new String(rvdMsgByte);

     System.out.println("Received: " + rvdMsgTxt);       
  }

  catch(IOException ioe)
  {
     ioe.printStackTrace();
  }
}
}

最佳答案

根据显示的代码,完全可以预期有时会得到空负载,因为如果负载数据包尚未到达:inFromDotNet.available() 将为零。

基本上,除了“当前有字节缓冲”(可能是为了在同步读取和异步读取之间进行选择)。

这里常用的方法有两种:

  • 使用 EOF 来指示有效载荷的结束,即读取直到套接字说它已关闭并且所有内容都已读取;如何检测这取决于特定的套接字 API(例如,在 .NET 中,当 Receive 返回一个非正数时)
  • 实现某种基本的框架协议(protocol)

如果您只向每个套接字发送一条消息,则第一个选项是相关的;如果您要为每个套接字发送多条消息,则第二个选项是必要的。基本的成帧协议(protocol)可以像“消息由换行符分隔”一样简单,但在许多情况下,您可能需要二进制安全的成帧,例如长度前缀。例如,您的 JSON 可能包含换行符,这可能会被错误地解释为帧的结尾。

在任何一种情况下:对于套接字,您几乎总是需要循环读取,因为数据可以拆分为多个数据包,和/或您的接收缓冲区大小可能太小。因此,通常情况下,您会循环并缓冲所有有效负载,直到检测到 EOF 或帧结束,只有在那时才开始尝试处理内容。特别是,在你知道你拥有完整的东西之前,你通常不应该尝试解码文本,因为多字节字符可能跨越多个“读取”/“接收”调用,所以:除非你使用有状态的文本解码器,否则你可能会错误地解码此类字符。

您看到的行为对于几乎所有平台和语言都是常见的;它不特定于 Java/C#。

关于java - C# 和 Java 服务器之间的 TCP 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53266539/

有关java - C# 和 Java 服务器之间的 TCP 通信的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  6. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  7. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  8. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐